diff options
author | ustieber | 2011-04-27 06:39:14 +0000 |
---|---|---|
committer | ustieber | 2011-04-27 06:39:14 +0000 |
commit | 2870751f2f0226fe1168988ffde72879b3a2d25b (patch) | |
tree | 67082a95ba5b97c69b52a4ac8970ff8ff052412f | |
parent | 008598c053a2dae230987eccab80ad86e1e41331 (diff) | |
download | org.eclipse.tcf-2870751f2f0226fe1168988ffde72879b3a2d25b.tar.gz org.eclipse.tcf-2870751f2f0226fe1168988ffde72879b3a2d25b.tar.xz org.eclipse.tcf-2870751f2f0226fe1168988ffde72879b3a2d25b.zip |
Add initial Target Explorer contribution
176 files changed, 13753 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/.classpath b/target_explorer/plugins/org.eclipse.tm.te.core/.classpath new file mode 100644 index 000000000..2d1a4302f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <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.tm.te.core/.project b/target_explorer/plugins/org.eclipse.tm.te.core/.project new file mode 100644 index 000000000..2c25cc880 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.tm.te.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/.settings/org.eclipse.jdt.core.prefs b/target_explorer/plugins/org.eclipse.tm.te.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..af7055514 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,77 @@ +#Wed Apr 27 07:52:47 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+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=error
+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.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=ignore
+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=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+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.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.5
diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tm.te.core/META-INF/MANIFEST.MF new file mode 100644 index 000000000..3db9197af --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.tm.te.core;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.tm.te.core.activator.CoreBundleActivator +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.core.runtime +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.tm.te.core.extensions;version="1.0.0", + org.eclipse.tm.te.core.nls;version="1.0.0" diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/build.properties b/target_explorer/plugins/org.eclipse.tm.te.core/build.properties new file mode 100644 index 000000000..f4ae97015 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/build.properties @@ -0,0 +1,5 @@ +source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties
diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/plugin.properties b/target_explorer/plugins/org.eclipse.tm.te.core/plugin.properties new file mode 100644 index 000000000..de370b5c7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/plugin.properties @@ -0,0 +1,12 @@ +################################################################################## +# Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved. +# This program and the accompanying materials are made available under the terms +# of the Eclipse Public License v1.0 which accompanies this distribution, and is +# available at http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Uwe Stieber (Wind River) - initial API and implementation +################################################################################## + +pluginName = Target Explorer, Core +providerName = Eclipse.org diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/activator/CoreBundleActivator.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/activator/CoreBundleActivator.java new file mode 100644 index 000000000..28f1d1c6a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/activator/CoreBundleActivator.java @@ -0,0 +1,55 @@ +/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved.
+ * This program and the accompanying materials are made available under the terms
+ * of the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.core.activator;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class CoreBundleActivator implements BundleActivator {
+ // The bundle context
+ private static BundleContext context;
+
+ /**
+ * Returns the bundle context
+ *
+ * @return the bundle context
+ */
+ public static BundleContext getContext() {
+ return context;
+ }
+
+ /**
+ * Convenience method which returns the unique identifier of this plugin.
+ */
+ public static String getUniqueIdentifier() {
+ if (getContext() != null && getContext().getBundle() != null) {
+ return getContext().getBundle().getSymbolicName();
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext bundleContext) throws Exception {
+ CoreBundleActivator.context = bundleContext;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext bundleContext) throws Exception {
+ CoreBundleActivator.context = null;
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/extensions/AbstractExtensionPointManager.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/extensions/AbstractExtensionPointManager.java new file mode 100644 index 000000000..9f2940382 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/extensions/AbstractExtensionPointManager.java @@ -0,0 +1,170 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.core.extensions; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tm.te.core.activator.CoreBundleActivator; +import org.eclipse.tm.te.core.nls.Messages; + +/** + * Target Explorer: Abstract extension point manager implementation. + */ +public abstract class AbstractExtensionPointManager<V> { + // Flag to mark the extension point manager initialized (extensions loaded). + private boolean fInitialized = false; + // The map of loaded extension listed by their unique ids + private Map<String, ExecutableExtensionProxy<V>> fExtensions = new LinkedHashMap<String, ExecutableExtensionProxy<V>>(); + + /** + * Constructor. + */ + public AbstractExtensionPointManager() { + } + + /** + * Returns if or if not the extension point manager got initialized already. + * <p> + * Initialized means that the manager read the extensions for the managed extension point. + * + * @return <code>True</code> if already initialized, <code>false</code> otherwise. + */ + protected boolean isInitialized() { + return fInitialized; + } + + /** + * Sets if or if not the extension point manager is initialized. + * <p> + * Initialized means that the manager has read the extensions for the managed extension point. + * + * @return <code>True</code> to set the extension point manager is initialized, <code>false</code> otherwise. + */ + protected void setInitialized(boolean initialized) { + fInitialized = initialized; + } + + /** + * Returns the map of managed extensions. If not loaded before, + * this methods trigger the loading of the extensions to the managed + * extension point. + * + * @return The map of extensions. + */ + protected Map<String, ExecutableExtensionProxy<V>> getExtensions() { + // Load and store the extensions thread-safe! + synchronized (fExtensions) { + if (!isInitialized()) { loadExtensions(); setInitialized(true); } + } + return fExtensions; + } + + /** + * Returns the extension point id to read. The method + * must return never <code>null</code>. + * + * @return The extension point id. + */ + protected abstract String getExtensionPointId(); + + /** + * Returns the configuration element name. The method + * must return never <code>null</code>. + * + * @return The configuration element name. + */ + protected abstract String getConfigurationElementName(); + + /** + * Creates the extension proxy instance. + * + * @param element The configuration element of the extension. Must be not <code>null</code>. + * @return The extension proxy instance. + * + * @throws CoreException If the extension proxy instantiation failed. + */ + protected ExecutableExtensionProxy<V> doCreateExtensionProxy(IConfigurationElement element) throws CoreException { + assert element != null; + return new ExecutableExtensionProxy<V>(element); + } + + /** + * Store the given extension to the given extensions store. Checks if an extension with the same id does exist + * already and throws an exception in this case. + * + * @param extensions The extensions store. Must not be <code>null</code>. + * @param candidate The extension. Must not be <code>null</code>. + * @param element The configuration element. Must not be <code>null</code>. + * + * @throws CoreException In case a extension with the same id as the given extension already exist. + */ + protected void doStoreExtensionTo(Map<String, ExecutableExtensionProxy<V>> extensions, ExecutableExtensionProxy<V> candidate, IConfigurationElement element) throws CoreException { + assert extensions != null && candidate != null && element != null; + + // If no extension with this id had been registered before, register now. + if (!fExtensions.containsKey(candidate.getId())) { + fExtensions.put(candidate.getId(), candidate); + } + else { + throw new CoreException(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + 0, + NLS.bind(Messages.Extension_error_duplicateExtension, candidate.getId(), element.getContributor().getName()), + null)); + } + } + + /** + * Loads the extensions for the managed extension point. + */ + protected void loadExtensions() { + // If already initialized, this method will do nothing. + if (isInitialized()) return; + + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint point = registry.getExtensionPoint(getExtensionPointId()); + if (point != null) { + IExtension[] extensions = point.getExtensions(); + for (IExtension extension : extensions) { + IConfigurationElement[] elements = extension.getConfigurationElements(); + for (IConfigurationElement element : elements) { + if (getConfigurationElementName().equals(element.getName())) { + try { + ExecutableExtensionProxy<V> candidate = doCreateExtensionProxy(element); + if (candidate.getId() != null) { + doStoreExtensionTo(fExtensions, candidate, element); + } else { + throw new CoreException(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + 0, + NLS.bind(Messages.Extension_error_missingRequiredAttribute, "id", element.getAttribute("label")), //$NON-NLS-1$ //$NON-NLS-2$ + null)); + } + } catch (CoreException e) { + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.Extension_error_invalidExtensionPoint, element.getDeclaringExtension().getUniqueIdentifier()), e)); + } + } + } + } + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/extensions/ExecutableExtension.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/extensions/ExecutableExtension.java new file mode 100644 index 000000000..eb08c9f45 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/extensions/ExecutableExtension.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.core.extensions; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tm.te.core.activator.CoreBundleActivator; +import org.eclipse.tm.te.core.nls.Messages; + + + +/** + * Target Explorer: Executable extension implementation. + */ +public class ExecutableExtension extends PlatformObject { + private String fId; + private String fLabel; + private String fDescription; + + /** + * Constructor. + */ + public ExecutableExtension() { + super(); + fId = null; + fLabel = ""; //$NON-NLS-1$ + fDescription = ""; //$NON-NLS-1$ + } + + /** + * Clone the initialization data to the given executable extension instance. + * + * @param other The destination executable extension instance. Must not be <code>null</code>. + */ + public void cloneInitializationData(ExecutableExtension other) { + assert other != null; + other.fId = fId; + other.fLabel = fLabel; + other.fDescription = fDescription; + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object) + */ + public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { + if (config != null) { + // Initialize the id field by reading the <id> extension attribute. + // Throws an exception if the id is empty or null. + fId = config.getAttribute("id"); //$NON-NLS-1$ + if (fId == null || fId.trim().length() == 0) { + throw createMissingMandatoryAttributeException("id", config.getContributor().getName()); //$NON-NLS-1$ + } + + // Initialize the label field by reading the <label> extension attribute if present. + fLabel = config.getAttribute("label"); //$NON-NLS-1$ + if (fLabel == null || fLabel.trim().length() == 0) fLabel = ""; //$NON-NLS-1$ + + // Initialize the description field by reading the "<description>" extension child element if present. + IConfigurationElement[] children = config.getChildren("description"); //$NON-NLS-1$ + // Only one description element is allow. All other will be ignored + if (children.length > 0) { + IConfigurationElement description = children[0]; + String value = description.getValue(); + fDescription = value != null ? value.trim() : ""; //$NON-NLS-1$ + } + } + } + + /** + * Creates a new {@link CoreException} to be thrown if a mandatory extension attribute + * is missing. + * + * @param attributeName The attribute name. Must be not <code>null</code>. + * @param extensionId The extension id. Must be not <code>null</code>. + * + * @return The {@link CoreException} instance. + */ + protected CoreException createMissingMandatoryAttributeException(String attributeName, String extensionId) { + assert attributeName != null && extensionId != null; + return new CoreException(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + 0, + NLS.bind(Messages.Extension_error_missingRequiredAttribute, attributeName, extensionId), + null)); + } + + /** + * Returns the unique id of the extension. The returned + * id must be never <code>null</code> or an empty string. + * + * @return The unique id. + */ + public String getId() { + return fId; + } + + /** + * Returns the label of the extension. + * + * @return The label or an empty string. + */ + public String getLabel() { + return fLabel != null ? fLabel : ""; //$NON-NLS-1$ + } + + /** + * Returns the description of the extension. + * + * @return The description or an empty string. + */ + public String getDescription() { + return fDescription != null ? fDescription : ""; //$NON-NLS-1$ + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/extensions/ExecutableExtensionProxy.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/extensions/ExecutableExtensionProxy.java new file mode 100644 index 000000000..68e5cb135 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/extensions/ExecutableExtensionProxy.java @@ -0,0 +1,156 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.core.extensions; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tm.te.core.activator.CoreBundleActivator; +import org.eclipse.tm.te.core.nls.Messages; + + +/** + * Target Explorer: Executable extension proxy implementation. + */ +public class ExecutableExtensionProxy<V> { + // The extension instance. Created on first access + private V fInstance; + // The configuration element + private final IConfigurationElement fElement; + // The unique id of the extension. + private String fId; + + /** + * Constructor. + * + * @param element The configuration element. Must not be <code>null</code>. + * @throws CoreException In case the configuration element attribute <i>id</i> is <code>null</code> or empty. + */ + public ExecutableExtensionProxy(IConfigurationElement element) throws CoreException { + assert element != null; + fElement = element; + + // Extract the extension attributes + fId = element.getAttribute("id"); //$NON-NLS-1$ + if (fId == null || fId.trim().length() == 0) { + throw new CoreException(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + 0, + NLS.bind(Messages.Extension_error_missingRequiredAttribute, "id", element.getContributor().getName()), //$NON-NLS-1$ + null)); + } + + fInstance = null; + } + + /** + * Constructor. + * + * @param id The id for this instance. + * @param instance The instance to add to proxy. + */ + public ExecutableExtensionProxy(String id, V instance) { + assert id!= null && instance != null; + fId = id; + fInstance = instance; + fElement = null; + } + + /** + * Returns the extensions unique id. + * + * @return The unique id. + */ + public String getId() { + return fId; + } + + /** + * Returns the configuration element for this extension. + * + * @return The configuration element. + */ + public IConfigurationElement getConfigurationElement() { + return fElement; + } + + /** + * Reset the extension instance to <code>null</code> and force the + * creation of a new extension instance on the next {@link #getInstance()} + * method invocation. + * + * @return The current extension instance or <code>null</code> if none. + */ + public V reset() { + V oldExtension = fInstance; + fInstance = null; + return oldExtension; + } + + /** + * Returns the extension class instance. The contributing + * plug-in will be activated if not yet activated anyway. + * + * @return The extension class instance or <code>null</code> if the instantiation fails. + */ + public V getInstance() { + if (fInstance == null) fInstance = newInstance(); + return fInstance; + } + + /** + * Returns always a new extension class instance which is different + * to what {@link #getInstance()} would return. + * + * @return A new extension class instance or <code>null</code> if the instantiation fails. + */ + @SuppressWarnings("unchecked") + public V newInstance() { + IConfigurationElement element = getConfigurationElement(); + assert element != null; + // The "class" to load can be specified either as attribute or as child element + if (element != null && (element.getAttribute("class") != null || element.getChildren("class").length > 0)) { //$NON-NLS-1$ //$NON-NLS-2$ + try { + return (V)element.createExecutableExtension("class"); //$NON-NLS-1$ + } catch (Exception e) { + // Possible exceptions: CoreException, ClassCastException. + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.Extension_error_invalidExtensionPoint, element.getDeclaringExtension().getUniqueIdentifier()), e)); + } + } + return null; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + // Proxie's are equal if they have encapsulate an element + // with the same unique id + if (obj instanceof ExecutableExtensionProxy<?>) { + return getId().equals(((ExecutableExtensionProxy<?>)obj).getId()); + } + return super.equals(obj); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + // The hash code of a proxy is the one from the id + return getId().hashCode(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/nls/Messages.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/nls/Messages.java new file mode 100644 index 000000000..f7488e2c3 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/nls/Messages.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.core.nls; + +import org.eclipse.osgi.util.NLS; + +/** + * Target Explorer Core plugin externalized strings management. + */ +public class Messages extends NLS { + + // The plug-in resource bundle name + private static final String BUNDLE_NAME = "org.eclipse.tm.te.core.nls.Messages"; //$NON-NLS-1$ + + /** + * Static constructor. + */ + static { + // Load message values from bundle file + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + // **** Declare externalized string id's down here ***** + + public static String Extension_error_missingRequiredAttribute; + public static String Extension_error_duplicateExtension; + public static String Extension_error_invalidExtensionPoint; +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/nls/Messages.properties new file mode 100644 index 000000000..0c0a2348a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/nls/Messages.properties @@ -0,0 +1,8 @@ +# +# org.eclipse.tm.te.core +# Externalized Strings. +# + +Extension_error_missingRequiredAttribute=Required attribute "{0}" missing for extension "{1}"! +Extension_error_duplicateExtension=Duplicate extension with id ''{0}''. Ignoring duplicated contribution from contributor ''{1}''! +Extension_error_invalidExtensionPoint=Failed to instantiate the executable extension from extension point ''{0}''. diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.classpath b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.classpath new file mode 100644 index 000000000..64c5e31b7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <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.tm.te.tcf.core/.options b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.options new file mode 100644 index 000000000..70df03d93 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.options @@ -0,0 +1 @@ +org.eclipse.tm.te.tcf.core/debug/channels = false diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.project b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.project new file mode 100644 index 000000000..30df93801 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.tm.te.tcf.core</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.settings/org.eclipse.jdt.core.prefs b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..d59c65841 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,77 @@ +#Thu Mar 17 14:57:00 CET 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +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=error +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.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=ignore +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=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +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.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.5 diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/META-INF/MANIFEST.MF new file mode 100644 index 000000000..3c9be0a22 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/META-INF/MANIFEST.MF @@ -0,0 +1,15 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.tm.te.tcf.core;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.tm.te.tcf.core.activator.CoreBundleActivator +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0", + org.eclipse.tm.tcf.core;bundle-version="0.3.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.tm.te.tcf.core;version="1.0.0", + org.eclipse.tm.te.tcf.core.interfaces;version="1.0.0", + org.eclipse.tm.te.tcf.core.interfaces.listeners;version="1.0.0" diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/build.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/build.properties new file mode 100644 index 000000000..30b2fc40b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/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.tm.te.tcf.core/plugin.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/plugin.properties new file mode 100644 index 000000000..62ae97a5d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/plugin.properties @@ -0,0 +1,12 @@ +################################################################################## +# Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved. +# This program and the accompanying materials are made available under the terms +# of the Eclipse Public License v1.0 which accompanies this distribution, and is +# available at http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Uwe Stieber (Wind River) - initial API and implementation +################################################################################## + +pluginName = Target Explorer, Common TCF Extensions +providerName = Eclipse.org diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/plugin.xml b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/plugin.xml new file mode 100644 index 000000000..7d5c60d61 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/plugin.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> + +<!-- TCF framework startup participant --> + <extension point="org.eclipse.tm.tcf.startup"> + <class name="org.eclipse.tm.te.tcf.core.internal.Startup"/> + </extension> + +</plugin> diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/Tcf.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/Tcf.java new file mode 100644 index 000000000..a89f0de62 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/Tcf.java @@ -0,0 +1,290 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.IAdapterManager; +import org.eclipse.core.runtime.Platform; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.protocol.Protocol.ChannelOpenListener; +import org.eclipse.tm.te.tcf.core.interfaces.IChannelManager; +import org.eclipse.tm.te.tcf.core.interfaces.listeners.IChannelStateChangeListener; +import org.eclipse.tm.te.tcf.core.interfaces.listeners.IProtocolStateChangeListener; +import org.eclipse.tm.te.tcf.core.internal.ChannelManager; +import org.eclipse.tm.te.tcf.core.internal.Startup; +import org.eclipse.tm.te.tcf.core.internal.interfaces.IChannelOpenListener; +import org.eclipse.tm.te.tcf.core.internal.listener.InternalChannelOpenListener; + + +/** + * The main entry point to access the TCF framework extensions. + */ +public final class Tcf { + /* default */ IChannelManager fChannelManager; + + /* default */ ChannelOpenListener fChannelOpenListener; + + /* default */ final List<IProtocolStateChangeListener> fProtocolStateChangeListeners = new ArrayList<IProtocolStateChangeListener>(); + /* default */ final List<IChannelStateChangeListener> fChannelStateChangeListeners = new ArrayList<IChannelStateChangeListener>(); + + + /* + * Thread save singleton instance creation. + */ + private static class LazyInstance { + public static Tcf fInstance = new Tcf(); + } + + /** + * Constructor. + */ + /* default */ Tcf() { + super(); + } + + /** + * Returns the singleton instance. + */ + /* default */ static Tcf getInstance() { + return LazyInstance.fInstance; + } + + /** + * Executes the given runnable within the TCF protocol dispatch thread. + * <p> + * <b>Note:</b> Code which is executed in the TCF protocol dispatch thread + * cannot use any blocking API! + * + * @param runnable The runnable. Must be not <code>null</code>. + */ + private static final void runSafe(Runnable runnable) { + assert runnable != null; + + if (Protocol.isDispatchThread()) { + runnable.run(); + } else { + Protocol.invokeAndWait(runnable); + } + } + + /** + * Adds a listener that will be notified once the TCF framework state changes. + * + * @param listener The listener. Must be not <code>null</code>. + */ + public static final void addProtocolStateChangeListener(IProtocolStateChangeListener listener) { + assert Protocol.isDispatchThread() && listener != null; + + Tcf tcf = getInstance(); + assert tcf != null; + + if (!tcf.fProtocolStateChangeListeners.contains(listener)) { + tcf.fProtocolStateChangeListeners.add(listener); + } + } + + /** + * Removes the specified protocol state change listener. + * + * @param listener The listener. Must be not <code>null</code>. + */ + public static final void removeProtocolStateChangeListener(IProtocolStateChangeListener listener) { + assert Protocol.isDispatchThread() && listener != null; + + Tcf tcf = getInstance(); + assert tcf != null; + + tcf.fProtocolStateChangeListeners.remove(listener); + } + + /** + * Adds a listener that will be notified once the TCF framework state changes. + * + * @param listener The listener. Must be not <code>null</code>. + */ + public static final void addChannelStateChangeListener(IChannelStateChangeListener listener) { + assert Protocol.isDispatchThread() && listener != null; + + Tcf tcf = getInstance(); + assert tcf != null; + + if (!tcf.fChannelStateChangeListeners.contains(listener)) { + tcf.fChannelStateChangeListeners.add(listener); + } + } + + /** + * Removes the specified protocol state change listener. + * + * @param listener The listener. Must be not <code>null</code>. + */ + public static final void removeChannelStateChangeListener(IChannelStateChangeListener listener) { + assert Protocol.isDispatchThread() && listener != null; + + Tcf tcf = getInstance(); + assert tcf != null; + + tcf.fChannelStateChangeListeners.remove(listener); + } + + /** + * Fires the channel state change listeners. + * + * @param channel The channel which changed state. Must be not <code>null</code>. + * @param state The new state. + */ + public static final void fireChannelStateChangeListeners(final IChannel channel, final int state) { + assert channel != null; + + Tcf tcf = getInstance(); + assert tcf != null; + + final IChannelStateChangeListener[] listeners = tcf.fChannelStateChangeListeners.toArray(new IChannelStateChangeListener[tcf.fChannelStateChangeListeners.size()]); + if (listeners.length > 0) { + Protocol.invokeLater(new Runnable() { + public void run() { + for (IChannelStateChangeListener listener : listeners) { + listener.stateChanged(channel, state); + } + } + }); + } + } + + /** + * Returns if or if not the TCF framework is up and running. + * + * @return <code>True</code> if the framework is up and running, <code>false</code> otherwise. + */ + public static final boolean isRunning() { + return Startup.isStarted(); + } + + /** + * Startup TCF related services and listeners once the core + * TCF framework starts up. + * <p> + * <b>Note:</b> The method is expected to be called within the TCF protocol dispatch thread. + * + * @see Startup#setStarted(boolean) + */ + public static void start() { + assert Protocol.isDispatchThread(); + + Tcf tcf = getInstance(); + assert tcf != null; + + // Create and register the global channel open listener + if (tcf.fChannelOpenListener == null) { + tcf.fChannelOpenListener = new InternalChannelOpenListener(); + Protocol.addChannelOpenListener(tcf.fChannelOpenListener); + } + + // Signal to interested listeners that we've started up + final IProtocolStateChangeListener[] listeners = tcf.fProtocolStateChangeListeners.toArray(new IProtocolStateChangeListener[tcf.fProtocolStateChangeListeners.size()]); + if (listeners.length > 0) { + Protocol.invokeLater(new Runnable() { + public void run() { + for (IProtocolStateChangeListener listener : listeners) { + listener.stateChanged(true); + } + } + }); + } + } + + /** + * Shutdown TCF related services and listeners once the core + * TCF framework shuts down. + * <p> + * <b>Note:</b> The method is expected to be called within the TCF protocol dispatch thread. + * + * @see Startup#setStarted(boolean) + */ + public static void stop() { + assert Protocol.isDispatchThread(); + + Tcf tcf = getInstance(); + assert tcf != null; + + // Unregister the channel open listener of created + if (tcf.fChannelOpenListener != null) { + Protocol.removeChannelOpenListener(tcf.fChannelOpenListener); + tcf.fChannelOpenListener = null; + } + + // Signal to interested listeners that we've just went down + final IProtocolStateChangeListener[] listeners = tcf.fProtocolStateChangeListeners.toArray(new IProtocolStateChangeListener[tcf.fProtocolStateChangeListeners.size()]); + if (listeners.length > 0) { + Protocol.invokeLater(new Runnable() { + public void run() { + for (IProtocolStateChangeListener listener : listeners) { + listener.stateChanged(false); + } + } + }); + } + } + + /** + * Returns the channel manager instance. + * <p> + * <b>Note:</b> The method will create the channel manager instance on + * first invocation. + * + * @return The channel manager instance. + */ + public static IChannelManager getChannelManager() { + final Tcf tcf = getInstance(); + assert tcf != null; + + runSafe(new Runnable() { + public void run() { + assert Protocol.isDispatchThread(); + + if (tcf.fChannelManager == null) { + // We have to create the channel manager + tcf.fChannelManager = new ChannelManager(); + } + } + }); + + return tcf.fChannelManager; + } + + /** + * Returns an object which is an instance of the given class associated with the given object. + * Returns <code>null</code> if no such object can be found. + * + * @param adapter The type of adapter to look up + * @return An object castable to the given adapter type, or <code>null</code> + * if the given adaptable object does not have an available adapter of the given type + * + * @see IAdapterManager#getAdapter(Object, Class) + */ + public static Object getAdapter(Class<?> adapter) { + assert adapter != null; + + Tcf tcf = getInstance(); + assert tcf != null; + + if (IChannelManager.class.equals(adapter)) { + return tcf.fChannelManager; + } + if (IChannelOpenListener.class.equals(adapter)) { + return tcf.fChannelOpenListener; + } + + return Platform.getAdapterManager().getAdapter(tcf, adapter); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/activator/CoreBundleActivator.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/activator/CoreBundleActivator.java new file mode 100644 index 000000000..cd6b211d4 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/activator/CoreBundleActivator.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.activator; + +import org.eclipse.tm.te.tcf.core.internal.Startup; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + + +/** + * The activator class controls the plug-in life cycle + */ +public class CoreBundleActivator implements BundleActivator { + // The bundle context + private static BundleContext context; + + /** + * Returns the bundle context + * + * @return the bundle context + */ + public static BundleContext getContext() { + return context; + } + + /** + * Convenience method which returns the unique identifier of this plugin. + */ + public static String getUniqueIdentifier() { + if (getContext() != null && getContext().getBundle() != null) { + return getContext().getBundle().getSymbolicName(); + } + return null; + } + + /* (non-Javadoc) + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext bundleContext) throws Exception { + CoreBundleActivator.context = bundleContext; + } + + /* (non-Javadoc) + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception { + CoreBundleActivator.context = null; + + // Mark the core framework as not started anymore + Startup.setStarted(false); + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/interfaces/IChannelManager.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/interfaces/IChannelManager.java new file mode 100644 index 000000000..2a52c50f7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/interfaces/IChannelManager.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.interfaces; + +import java.util.Map; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IPeer; + +/** + * TCF channel manager public API declaration. + */ +public interface IChannelManager extends IAdaptable { + + /** + * Client call back interface for openChannel(...). + */ + interface DoneOpenChannel { + /** + * Called when the channel fully opened or failed to open. + * + * @param error The error description if operation failed, <code>null</code> if succeeded. + * @param channel The channel object or <code>null</code>. + */ + void doneOpenChannel(Throwable error, IChannel channel); + } + + /** + * Opens a new channel to communicate with the given peer. + * <p> + * The method can be called from any thread context. + * + * @param peer The peer. Must be not <code>null</code>. + * @param done The client callback. Must be not <code>null</code>. + */ + public void openChannel(IPeer peer, DoneOpenChannel done); + + /** + * Opens a new channel to communicate with the peer described by the + * given peer attributes. + * <p> + * The method can be called from any thread context. + * + * @param peerAttributes The peer attributes. Must be not <code>null</code>. + * @param done The client callback. Must be not <code>null</code>. + */ + public void openChannel(Map<String, String> peerAttributes, DoneOpenChannel done); +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/interfaces/listeners/IChannelStateChangeListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/interfaces/listeners/IChannelStateChangeListener.java new file mode 100644 index 000000000..c6dfd3379 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/interfaces/listeners/IChannelStateChangeListener.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.interfaces.listeners; + +import org.eclipse.tm.tcf.protocol.IChannel; + +/** + * Interface for clients to implement that wishes to listen + * channel state changes, like opening and closing of a channel. + */ +public interface IChannelStateChangeListener { + + /** + * Invoked if the channel state has changed. + * + * @param channel The channel which changed state. + * @param state The new state. + */ + public void stateChanged(IChannel channel, int state); +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/interfaces/listeners/IProtocolStateChangeListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/interfaces/listeners/IProtocolStateChangeListener.java new file mode 100644 index 000000000..99a2efc3a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/interfaces/listeners/IProtocolStateChangeListener.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.interfaces.listeners; + +/** + * Interface for clients to implement that wishes to listen + * for the TCF protocol framework to come up and shutdown. + */ +public interface IProtocolStateChangeListener { + + /** + * Invoked if the TCF framework comes up, <i>state == true</i>, or + * if it shuts down, <i>state == false</i>. + * + * @param state The current TCF framework state. + */ + public void stateChanged(boolean state); +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/ChannelManager.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/ChannelManager.java new file mode 100644 index 000000000..9170cb29f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/ChannelManager.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.internal; + +import java.util.Map; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.tm.tcf.core.AbstractPeer; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.core.interfaces.IChannelManager; + + +/** + * TCF channel manager implementation. + */ +public final class ChannelManager extends PlatformObject implements IChannelManager { + + /** + * Constructor. + */ + public ChannelManager() { + super(); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.core.interfaces.IChannelManager#openChannel(org.eclipse.tm.tcf.protocol.IPeer, org.eclipse.tm.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel) + */ + public void openChannel(final IPeer peer, final DoneOpenChannel done) { + if (Protocol.isDispatchThread()) { + internalOpenChannel(peer, done); + } else { + Protocol.invokeLater(new Runnable() { + public void run() { + internalOpenChannel(peer, done); + } + }); + } + } + + /** + * Internal implementation of {@link #openChannel(IPeer, org.eclipse.tm.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel)}. + * <p> + * Method must be called within the TCF dispatch thread. + * + * @param peer The peer. Must be not <code>null</code>. + * @param done The client callback. Must be not <code>null</code>. + */ + /* default */ void internalOpenChannel(final IPeer peer, final DoneOpenChannel done) { + assert peer != null; + assert done != null; + assert Protocol.isDispatchThread(); + + // Open the channel + final IChannel channel = peer.openChannel(); + // Register the channel listener + if (channel != null) { + channel.addChannelListener(new IChannel.IChannelListener() { + + public void onChannelOpened() { + // Remove ourself as listener from the channel + channel.removeChannelListener(this); + // Channel opening succeeded + done.doneOpenChannel(null, channel); + } + + public void onChannelClosed(Throwable error) { + // Remove ourself as listener from the channel + channel.removeChannelListener(this); + // Channel opening failed + done.doneOpenChannel(error, channel); + } + + public void congestionLevel(int level) { + // ignored + } + }); + } else { + // Channel is null? Something went terrible wrong. + done.doneOpenChannel(new Exception("Unexpected null return value from IPeer#openChannel()!"), null); //$NON-NLS-1$ + } + + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.core.interfaces.IChannelManager#openChannel(java.util.Map, org.eclipse.tm.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel) + */ + public void openChannel(final Map<String, String> peerAttributes, final DoneOpenChannel done) { + if (Protocol.isDispatchThread()) { + internalOpenChannel(peerAttributes, done); + } else { + Protocol.invokeLater(new Runnable() { + public void run() { + internalOpenChannel(peerAttributes, done); + } + }); + } + } + + /** + * Internal implementation of {@link #openChannel(Map, org.eclipse.tm.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel)}. + * <p> + * Method must be called within the TCF dispatch thread. + * + * @param peerAttributes The peer attributes. Must be not <code>null</code>. + * @param done The client callback. Must be not <code>null</code>. + */ + /* default */ void internalOpenChannel(final Map<String, String> peerAttributes, final DoneOpenChannel done) { + assert peerAttributes != null; + assert done != null; + assert Protocol.isDispatchThread(); + internalOpenChannel(getOrCreatePeerInstance(peerAttributes), done); + } + + /** + * Tries to find an existing peer instance or create an new {@link IPeer} + * instance if not found. + * <p> + * <b>Note:</b> This method must be invoked at the TCF dispatch thread. + * + * @param peerAttributes The peer attributes. Must be not <code>null</code>. + * @return The peer instance. + */ + private IPeer getOrCreatePeerInstance(final Map<String, String> peerAttributes) { + assert peerAttributes != null; + assert Protocol.isDispatchThread(); + + // Get the peer id from the properties + String peerId = peerAttributes.get(IPeer.ATTR_ID); + assert peerId != null; + + // Look the peer via the Locator Service. + IPeer peer = Protocol.getLocator().getPeers().get(peerId); + // If not peer could be found, create a new one + if (peer == null) { + peer = new AbstractPeer(peerAttributes); + } + + // Return the peer instance + return peer; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/Startup.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/Startup.java new file mode 100644 index 000000000..4fd135b58 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/Startup.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.internal; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.core.Tcf; +import org.eclipse.tm.te.tcf.core.activator.CoreBundleActivator; + + +/** + * Calls loaded by the TCF core framework when the framework is fired up. The static + * constructor of the class will trigger whatever is necessary in this case. + * <p> + * <b>Note:</b> This will effectively trigger {@link CoreBundleActivator#start(org.osgi.framework.BundleContext)} + * to be called. + */ +public class Startup { + // Atomic boolean to store the started state of the TCF core framework + /* default */ final static AtomicBoolean STARTED = new AtomicBoolean(false); + + static { + // We might get here on shutdown as well, and if TCF has not + // been loaded, than we will run into an NPE. Lets double check. + if (Protocol.getEventQueue() != null) { + // Initialize the framework status by scheduling a simple + // runnable to execute and be invoked once the framework + // is fully up and usable. + Protocol.invokeLater(new Runnable() { + public void run() { + // Core framework is scheduling the runnables, means it is started. + setStarted(true); + } + }); + } + } + + /** + * Set the core framework started state to the given state. + * + * @param started <code>True</code> when the framework is started, <code>false</code> otherwise. + */ + public static final void setStarted(boolean started) { + STARTED.set(started); + + // Start/Stop should be called in the TCF protocol dispatch thread + if (Protocol.getEventQueue() != null) { + Protocol.invokeLater(new Runnable() { + public void run() { + // Catch IllegalStateException: TCF event dispatcher has shut down + try { + if (STARTED.get()) Tcf.start(); else Tcf.stop(); + } catch (IllegalStateException e) { + if (!STARTED.get() && "TCF event dispatcher has shut down".equals(e.getLocalizedMessage())) { //$NON-NLS-1$ + // ignore the exception on shutdown + } else { + // re-throw in any other case + throw e; + } + } + } + }); + } + } + + /** + * Returns if or if not the core framework has been started. + * + * @return <code>True</code> when the framework is started, <code>false</code> otherwise. + */ + public static final boolean isStarted() { + return STARTED.get(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/interfaces/IChannelOpenListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/interfaces/IChannelOpenListener.java new file mode 100644 index 000000000..3a0273cac --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/interfaces/IChannelOpenListener.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.internal.interfaces; + +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.Protocol.ChannelOpenListener; + +/** + * Enhanced channel open listener interface for internal use. + */ +public interface IChannelOpenListener extends ChannelOpenListener { + + /** + * Stores the given channel listener to the internal map. The map + * key is the given channel. If the given channel listener is <code>null</code>, + * the channel is removed from the internal map. + * + * @param channel The channel. Must be not <code>null</code>. + * @param listener The channel listener or <code>null</code>. + */ + public void setChannelListener(IChannel channel, IChannel.IChannelListener listener); +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/listener/InternalChannelListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/listener/InternalChannelListener.java new file mode 100644 index 000000000..2b533fb84 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/listener/InternalChannelListener.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.internal.listener; + +import org.eclipse.osgi.util.NLS; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.te.tcf.core.Tcf; +import org.eclipse.tm.te.tcf.core.internal.interfaces.IChannelOpenListener; +import org.eclipse.tm.te.tcf.core.internal.nls.Messages; +import org.eclipse.tm.te.tcf.core.internal.utils.LogUtils; + + +/** + * Internal channel listener. Attached to a TCF channel for tracing purpose. + */ +public class InternalChannelListener implements IChannel.IChannelListener { + // The reference to the channel + private final IChannel fChannel; + + /** + * Constructor. + * + * @param channel The channel. Must be not <code>null</code>. + */ + public InternalChannelListener(IChannel channel) { + assert channel != null; + fChannel = channel; + } + + /** + * Return the associated channel. + * + * @return The channel instance. + */ + protected final IChannel getChannel() { + return fChannel; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.protocol.IChannel.IChannelListener#congestionLevel(int) + */ + public void congestionLevel(int level) { + } + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.protocol.IChannel.IChannelListener#onChannelClosed(java.lang.Throwable) + */ + public void onChannelClosed(Throwable error) { + // Detach the listeners cleanly + detachListeners(getChannel()); + + // Construct the cause message + String cause = ""; //$NON-NLS-1$ + if (error != null) { + cause = NLS.bind(Messages.InternalChannelListener_onChannelClosed_cause, error.getLocalizedMessage()); + } + + // Trace the channel closing + LogUtils.logMessageForChannel(getChannel(), NLS.bind(Messages.InternalChannelListener_onChannelClosed_message, cause), "debug/channels", this); //$NON-NLS-1$ + + // Fire the property change event for the channel + Tcf.fireChannelStateChangeListeners(getChannel(), IChannel.STATE_CLOSED); + } + + /** + * Detach all registered listeners from the given channel. + * + * @param channel The channel. Must not be <code>null</code>. + */ + protected void detachListeners(IChannel channel) { + assert channel != null; + + // Cleanly remove all listeners from the channel + channel.removeChannelListener(this); + + // And remove the listener references from the global channel open listener + IChannelOpenListener openListener = (IChannelOpenListener)Tcf.getAdapter(IChannelOpenListener.class); + if (openListener != null) openListener.setChannelListener(channel, null); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.protocol.IChannel.IChannelListener#onChannelOpened() + */ + public void onChannelOpened() { + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/listener/InternalChannelOpenListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/listener/InternalChannelOpenListener.java new file mode 100644 index 000000000..70fd1367a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/listener/InternalChannelOpenListener.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.internal.listener; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IChannel.IChannelListener; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.core.Tcf; +import org.eclipse.tm.te.tcf.core.internal.interfaces.IChannelOpenListener; +import org.eclipse.tm.te.tcf.core.internal.nls.Messages; +import org.eclipse.tm.te.tcf.core.internal.utils.LogUtils; + + +/** + * Internal channel open listener taking care of logging and caching. + */ +public class InternalChannelOpenListener implements IChannelOpenListener { + // Static map containing the channel listeners per channel. Access to the + // map should happen from the TCF protocol dispatch thread only. + private final Map<IChannel, IChannel.IChannelListener> fChannelListeners = new HashMap<IChannel, IChannel.IChannelListener>(); + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.protocol.Protocol.ChannelOpenListener#onChannelOpen(org.eclipse.tm.tcf.protocol.IChannel) + */ + public void onChannelOpen(IChannel channel) { + assert channel != null && Protocol.isDispatchThread(); + + // Trace the channel opening + LogUtils.logMessageForChannel(channel, Messages.InternalChannelOpenListener_onChannelOpen_message, "debug/channels", this); //$NON-NLS-1$ + + // As the channel has just opened, there should be no channel listener, but better be safe and check. + IChannel.IChannelListener channelListener = fChannelListeners.remove(channel); + if (channelListener != null) channel.removeChannelListener(channelListener); + // Create a new channel listener instance + channelListener = new InternalChannelListener(channel); + // Add the channel listener to the global map + setChannelListener(channel, channelListener); + // Attach channel listener to the channel + channel.addChannelListener(channelListener); + + // Fire the property change event for the channel + Tcf.fireChannelStateChangeListeners(channel, IChannel.STATE_OPEN); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.core.internal.interfaces.IChannelOpenListener#setChannelListener(org.eclipse.tm.tcf.protocol.IChannel, org.eclipse.tm.tcf.protocol.IChannel.IChannelListener) + */ + public void setChannelListener(IChannel channel, IChannelListener listener) { + assert channel != null; + if (listener != null) fChannelListeners.put(channel, listener); + else fChannelListeners.remove(channel); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/nls/Messages.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/nls/Messages.java new file mode 100644 index 000000000..9bb3b6f87 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/nls/Messages.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.internal.nls; + +import java.lang.reflect.Field; + +import org.eclipse.osgi.util.NLS; + +/** + * Plug-in externalized strings management. + */ +public class Messages extends NLS { + + // The plug-in resource bundle name + private static final String BUNDLE_NAME = "org.eclipse.tm.te.tcf.core.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 InternalChannelOpenListener_onChannelOpen_message; + + public static String InternalChannelListener_onChannelClosed_message; + public static String InternalChannelListener_onChannelClosed_cause; + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/nls/Messages.properties new file mode 100644 index 000000000..5c3039f1a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/nls/Messages.properties @@ -0,0 +1,9 @@ +# +# org.eclipse.tm.te.tcf.core +# Externalized Strings. +# + +InternalChannelOpenListener_onChannelOpen_message=Channel opened. + +InternalChannelListener_onChannelClosed_message=Channel closed. {0} +InternalChannelListener_onChannelClosed_cause=; Possibly caused by: {0} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/utils/LogUtils.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/utils/LogUtils.java new file mode 100644 index 000000000..0db70c280 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.core/src/org/eclipse/tm/te/tcf/core/internal/utils/LogUtils.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.core.internal.utils; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.te.tcf.core.activator.CoreBundleActivator; + + +/** + * Logging utilities helper implementations. + */ +public final class LogUtils { + + /** + * Log the given message for the given channel. + * + * @param channel The channel. Must not be <code>null</code>. + * @param message The message to log. Must not be <code>null</code>. + * @param slotId The Eclipse debug slot id which must be enabled to log the message. Must not be <code>null</code>. + * @param clazz The invoking class or <code>null</code>. + */ + public static void logMessageForChannel(IChannel channel, String message, String slotId, Object clazz) { + assert channel != null && message != null && slotId != null; + + // Trace the message + String fullMessage = channel.toString() + ": " + message; //$NON-NLS-1$ + + if (Boolean.parseBoolean(Platform.getDebugOption(CoreBundleActivator.getUniqueIdentifier() + "/" + slotId))) { //$NON-NLS-1$ + IStatus status = new Status(IStatus.INFO, CoreBundleActivator.getUniqueIdentifier(), fullMessage.trim()); + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/.classpath b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/.classpath new file mode 100644 index 000000000..64c5e31b7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/.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/J2SE-1.5"/> + <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.tm.te.tcf.filesystem/.project b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/.project new file mode 100644 index 000000000..c565bd013 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.tm.te.tcf.filesystem</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/.settings/org.eclipse.jdt.core.prefs b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..3de8327ea --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,77 @@ +#Wed Apr 06 15:35:33 CEST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +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=error +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.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=ignore +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=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +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.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.5 diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/META-INF/MANIFEST.MF new file mode 100644 index 000000000..ed3a1d414 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/META-INF/MANIFEST.MF @@ -0,0 +1,21 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.tm.te.tcf.filesystem;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.tm.te.tcf.filesystem.activator.UIPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0", + org.eclipse.ui;bundle-version="3.6.2", + org.eclipse.ui.forms;bundle-version="3.5.2", + org.eclipse.ui.navigator;bundle-version="3.5.0", + org.eclipse.tm.tcf.core;bundle-version="0.3.0", + org.eclipse.tm.te.tcf.core;bundle-version="1.0.0", + org.eclipse.tm.te.ui;bundle-version="1.0.0", + org.eclipse.tm.te.ui.views;bundle-version="1.0.0", + org.eclipse.tm.te.tcf.locator;bundle-version="1.0.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.tm.te.tcf.filesystem.controls;version="1.0.0", + org.eclipse.tm.te.tcf.filesystem.dialogs;version="1.0.0" diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/build.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/build.properties new file mode 100644 index 000000000..30b2fc40b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/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.tm.te.tcf.filesystem/icons/obj16/folder.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/icons/obj16/folder.gif Binary files differnew file mode 100644 index 000000000..5ae555a34 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/icons/obj16/folder.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/icons/obj16/rootdrive.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/icons/obj16/rootdrive.gif Binary files differnew file mode 100644 index 000000000..fd426343b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/icons/obj16/rootdrive.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/icons/obj16/rootdriveopen.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/icons/obj16/rootdriveopen.gif Binary files differnew file mode 100644 index 000000000..2171f7c38 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/icons/obj16/rootdriveopen.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/plugin.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/plugin.properties new file mode 100644 index 000000000..1cb3db872 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/plugin.properties @@ -0,0 +1,16 @@ +################################################################################## +# Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved. +# This program and the accompanying materials are made available under the terms +# of the Eclipse Public License v1.0 which accompanies this distribution, and is +# available at http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Uwe Stieber (Wind River) - initial API and implementation +################################################################################## + +pluginName = Target Explorer, TCF File System Extensions +providerName = Eclipse.org + +# ***** Editor Pages ***** + +FSExplorerEditorPage.name=File System diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/plugin.xml b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/plugin.xml new file mode 100644 index 000000000..5ab14daa3 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/plugin.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> + +<!-- Common navigator contributions --> + <extension point="org.eclipse.ui.navigator.viewer"> + <viewerContentBinding viewerId="org.eclipse.tm.te.ui.views.TargetExplorer"> + <includes> + <contentExtension + isRoot="false" + pattern="org.eclipse.tm.te.datasource.tcf.filesystem"/> + </includes> + </viewerContentBinding> + </extension> + + <extension point="org.eclipse.ui.navigator.navigatorContent"> + <navigatorContent + activeByDefault="true" + contentProvider="org.eclipse.tm.te.tcf.filesystem.controls.FSTreeContentProvider" + icon="icons/obj16/rootdrive.gif" + id="org.eclipse.tm.te.datasource.tcf.filesystem" + labelProvider="org.eclipse.tm.te.tcf.filesystem.controls.FSTreeLabelProvider" + name="Target File System (TCF)" + priority="normal"> + <triggerPoints> + <instanceof value="org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel"/> + <test property="org.eclipse.tm.te.tcf.locator.hasRemoteService" value="FileSystem"/> + </triggerPoints> + <possibleChildren> + <instanceof value="org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel"/> + <instanceof value="org.eclipse.tm.te.tcf.filesystem.controls.FSTreeNode"/> + </possibleChildren> + <commonSorter + class="org.eclipse.tm.te.tcf.filesystem.controls.FSTreeViewerSorter" + id="org.eclipse.tm.te.tcf.filesystem.navigator.sorter"> + </commonSorter> + </navigatorContent> + </extension> + +<!-- Target Explorer Details Editor page contributions --> + <extension point="org.eclipse.tm.te.ui.views.editorPages"> + <editorPage + class="org.eclipse.tm.te.tcf.filesystem.internal.explorer.FSExplorerEditorPage" + name="%FSExplorerEditorPage.name" + id="org.eclipse.tm.te.tcf.filesystem.FSExplorerEditorPage"> + </editorPage> + </extension> + +<!-- Target Explorer Details Editor page binding contributions --> + <extension point="org.eclipse.tm.te.ui.views.editorPageBindings"> + <editorPageBinding + id="org.eclipse.tm.te.tcf.filesystem.binding.FSExplorerEditorPage" + pageId="org.eclipse.tm.te.tcf.filesystem.FSExplorerEditorPage"> + <enablement> + <with variable="activeEditorInput"> + <and> + <adapt type="org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel"> + <test property="org.eclipse.tm.te.tcf.locator.hasRemoteService" value="FileSystem"/> + </adapt> + </and> + </with> + </enablement> + </editorPageBinding> + </extension> + +</plugin> diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/activator/UIPlugin.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/activator/UIPlugin.java new file mode 100644 index 000000000..d62ab5ff2 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/activator/UIPlugin.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.activator; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm.te.tcf.filesystem.internal.registries.InternalImageRegistry; +import org.eclipse.tm.te.ui.images.AbstractImageDescriptor; +import org.eclipse.tm.te.ui.images.AbstractImageRegistry; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + + +/** + * The activator class controls the plug-in life cycle + */ +public class UIPlugin extends AbstractUIPlugin { + // The shared instance + private static UIPlugin plugin; + + /** + * The constructor + */ + public UIPlugin() { + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static UIPlugin 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; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#initializeImageRegistry(org.eclipse.jface.resource.ImageRegistry) + */ + @Override + protected void initializeImageRegistry(ImageRegistry registry) { + if (registry instanceof InternalImageRegistry) { + ((InternalImageRegistry)registry).initialize(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#createImageRegistry() + */ + @Override + protected ImageRegistry createImageRegistry() { + return new InternalImageRegistry(this); + } + + /** + * Loads the image registered under the specified key from the image + * registry and returns the <code>Image</code> object instance. + * + * @param key The key the image is registered with. + * @return The <code>Image</code> object instance or <code>null</code>. + */ + public static Image getImage(String key) { + return getDefault().getImageRegistry().get(key); + } + + /** + * Loads the image registered under the specified key from the image + * registry and returns the <code>ImageDescriptor</code> object instance. + * + * @param key The key the image is registered with. + * @return The <code>ImageDescriptor</code> object instance or <code>null</code>. + */ + public static ImageDescriptor getImageDescriptor(String key) { + return getDefault().getImageRegistry().getDescriptor(key); + } + + /** + * Loads the image given by the specified image descriptor from the image + * registry. If the image has been loaded ones before already, the cached + * <code>Image</code> object instance is returned. Otherwise, the <code> + * Image</code> object instance will be created and cached before returned. + * + * @param descriptor The image descriptor. + * @return The corresponding <code>Image</code> object instance or <code>null</code>. + */ + public static Image getSharedImage(AbstractImageDescriptor descriptor) { + return ((AbstractImageRegistry)getDefault().getImageRegistry()).getSharedImage(descriptor); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeContentProvider.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeContentProvider.java new file mode 100644 index 000000000..c8c2eaa47 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeContentProvider.java @@ -0,0 +1,411 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.controls; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.IFileSystem; +import org.eclipse.tm.tcf.services.IFileSystem.DirEntry; +import org.eclipse.tm.tcf.services.IFileSystem.FileSystemException; +import org.eclipse.tm.tcf.services.IFileSystem.IFileHandle; +import org.eclipse.tm.te.tcf.core.Tcf; +import org.eclipse.tm.te.tcf.core.interfaces.IChannelManager; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModelProperties; +import org.eclipse.tm.te.ui.nodes.PendingOperation; +import org.eclipse.ui.PlatformUI; + + +/** + * Target Explorer: File system tree content provider implementation. + */ +public class FSTreeContentProvider implements ITreeContentProvider { + /** + * Static reference to the return value representing no elements. + */ + protected final static Object[] NO_ELEMENTS = new Object[0]; + + /** + * Static reference to the return value representing a pending child query. + */ + protected final static Object[] PENDING = new Object[] { new PendingOperation() }; + + + /* default */ IPeerModel fPeerNode = null; + private FSTreeNode fRootNode = null; + + private IChannel fChannel = null; + private IFileSystem fService = null; + + /* default */ Viewer fViewer = null; + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + fViewer = viewer; + if (oldInput != null && newInput == null) { + closeOpenChannel(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + closeOpenChannel(); + } + + /** + * Close the open communication channel and set back the node references. + */ + protected void closeOpenChannel() { + if (fChannel != null) { + final IChannel finChannel = fChannel; + if (Protocol.isDispatchThread()) { + finChannel.close(); + } else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + finChannel.close(); + } + }); + } + fChannel = null; + fService = null; + } + + fPeerNode = null; + fRootNode = null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getElements(java.lang.Object) + */ + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) + */ + public Object getParent(Object element) { + if (element instanceof FSTreeNode) { + return ((FSTreeNode)element).parent; + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) + */ + public Object[] getChildren(Object parentElement) { + assert parentElement != null; + + Object[] children = NO_ELEMENTS; + + // For the file system, we need the peer node + if (parentElement instanceof IPeerModel) { + // Is it the same peer node we have seen before? + if (fPeerNode == null || fPeerNode != null && !fPeerNode.equals(parentElement)) { + // Remember the peer node + fPeerNode = (IPeerModel)parentElement; + + // If we still have a channel open, for now, we just close the old channel + if (fChannel != null) { + final IChannel finChannel = fChannel; + if (Protocol.isDispatchThread()) { + finChannel.close(); + } else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + finChannel.close(); + } + }); + } + fChannel = null; + } + + IPeer peer = fPeerNode.getPeer(); + final int[] state = new int[1]; + Protocol.invokeAndWait(new Runnable() { + public void run() { + state[0] = fPeerNode.getIntProperty(IPeerModelProperties.PROP_STATE); + } + }); + if (peer != null && IPeerModelProperties.STATE_ERROR != state[0] && IPeerModelProperties.STATE_NOT_REACHABLE != state[0]) { + children = PENDING; + + Tcf.getChannelManager().openChannel(peer, new IChannelManager.DoneOpenChannel() { + @SuppressWarnings("synthetic-access") + public void doneOpenChannel(Throwable error, IChannel channel) { + assert Protocol.isDispatchThread(); + + if (channel != null) { + fChannel = channel; + + fService = fChannel.getRemoteService(IFileSystem.class); + if (fService != null) { + fRootNode = new FSTreeNode(); + fRootNode.type = "FSRootNode"; //$NON-NLS-1$ + fRootNode.childrenQueried = false; + fRootNode.childrenQueryRunning = true; + + Protocol.invokeLater(new Runnable() { + public void run() { + fService.roots(new IFileSystem.DoneRoots() { + public void doneRoots(IToken token, FileSystemException error, DirEntry[] entries) { + + if (fRootNode != null && error == null) { + + for (DirEntry entry : entries) { + FSTreeNode node = createNodeFromDirEntry(entry, true); + if (node != null) { + node.parent = fRootNode; + fRootNode.children.add(node); + } + } + + // Reset the children query markers + fRootNode.childrenQueryRunning = false; + fRootNode.childrenQueried = true; + } + + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + if (fViewer != null) fViewer.refresh(); + } + }); + } + }); + } + }); + + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + if (fViewer != null) fViewer.refresh(); + } + }); + } else { + // TCF file system service is not available, close the just opened channel + closeOpenChannel(); + } + + } + } + }); + } + } else if (fRootNode != null && fRootNode.childrenQueried) { + children = fRootNode.children.toArray(); + } + } else if (parentElement instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode)parentElement; + // Get possible children + children = node.children.toArray(); + // No children -> check for "childrenQueried" property. If false, trigger the query. + if (children.length == 0 && !node.childrenQueried && node.type.endsWith("DirNode")) { //$NON-NLS-1$ + children = PENDING; + + if (!node.childrenQueryRunning) { + final FSTreeNode parentNode = node; + + final String absName = getEntryAbsoluteName(node); + if (absName != null && fService != null) { + parentNode.childrenQueryRunning = true; + + Protocol.invokeLater(new Runnable() { + @SuppressWarnings("synthetic-access") + public void run() { + fService.opendir(absName, new IFileSystem.DoneOpen() { + + public void doneOpen(IToken token, FileSystemException error, final IFileHandle handle) { + + if (error == null && fService != null) { + // Read the directory content until finished + readdir(fService, handle, parentNode); + } else { + // In case of an error, we are done here + parentNode.childrenQueryRunning = false; + parentNode.childrenQueried = true; + } + } + }); + } + }); + } + } + + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + if (fViewer != null) fViewer.refresh(); + } + }); + } + } + + return children; + } + + /** + * Reads the content of a directory until the file system service signals EOF. + * + * @param service The file system service. Must be not <code>null</code>. + * @param handle The directory handle. Must be not <code>null</code>. + * @param parentNode The parent node receiving the entries. Must be not <code>null</code>. + * @param mode The notification mode to set to the parent node once done. + */ + protected void readdir(final IFileSystem service, final IFileHandle handle, final FSTreeNode parentNode) { + assert service != null && handle != null && parentNode != null; + + Protocol.invokeLater(new Runnable() { + @SuppressWarnings("synthetic-access") + public void run() { + fService.readdir(handle, new IFileSystem.DoneReadDir() { + + public void doneReadDir(IToken token, FileSystemException error, DirEntry[] entries, boolean eof) { + if (fService != null) { + // Close the handle if EOF is signaled or an error occurred. + if (eof) { + fService.close(handle, new IFileSystem.DoneClose() { + public void doneClose(IToken token, FileSystemException error) { + } + }); + } + + // Process the returned data + if (error == null && entries != null && entries.length > 0) { + for (DirEntry entry : entries) { + FSTreeNode node = createNodeFromDirEntry(entry, false); + if (node != null) { + node.parent = parentNode; + parentNode.children.add(node); + } + } + } + + if (eof) { + // Reset the children query markers + parentNode.childrenQueryRunning = false; + parentNode.childrenQueried = true; + } else { + // And invoke ourself again + readdir(service, handle, parentNode); + } + } + + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + if (fViewer instanceof StructuredViewer) ((StructuredViewer)fViewer).refresh(parentNode); + } + }); + } + }); + } + }); + } + + + /** + * Creates a tree node from the given directory entry. + * + * @param entry The directory entry. Must be not <code>null</code>. + * + * @return The tree node. + */ + protected FSTreeNode createNodeFromDirEntry(DirEntry entry, boolean entryIsRootNode) { + assert entry != null; + + FSTreeNode node = null; + + IFileSystem.FileAttrs attrs = entry.attrs; + + if (attrs == null || attrs != null && attrs.isDirectory()) { + node = new FSTreeNode(); + node.childrenQueried = false; + node.childrenQueryRunning = false; + node.attr = attrs; + node.name = entry.filename; + node.type = entryIsRootNode ? "FSRootDirNode" : "FSDirNode"; //$NON-NLS-1$ //$NON-NLS-2$ + } else if (attrs.isFile()) { + node = new FSTreeNode(); + node.childrenQueried = false; + node.childrenQueryRunning = false; + node.attr = attrs; + node.name = entry.filename; + node.type = "FSFileNode"; //$NON-NLS-1$ + } + + return node; + } + + /** + * Returns the absolute name for the given node. + * + * @param node The node. Must be not <code>null</code>. + * @return The absolute name. + */ + public static String getEntryAbsoluteName(FSTreeNode node) { + assert node != null; + + StringBuilder path = new StringBuilder(); + + // We have to walk upwards the hierarchy until the root node is found + FSTreeNode parent = node.parent; + while (parent != null && parent.type != null && parent.type.startsWith("FS")) { //$NON-NLS-1$ + if ("FSRootNode".equals(parent.type)) { //$NON-NLS-1$ + // We are done if reaching the root node + break; + } + + if (path.length() == 0) path.append(parent.name.replaceAll("\\\\", "/")); //$NON-NLS-1$ //$NON-NLS-2$ + else { + String name = parent.name.replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$ + if (!name.endsWith("/")) name = name + "/"; //$NON-NLS-1$ //$NON-NLS-2$ + path.insert(0, name); + } + + parent = parent.parent; + } + + if (path.length() > 0 && path.charAt(path.length() - 1) != '/') { + path.append("/"); //$NON-NLS-1$ + } + path.append(node.name); + + return path.toString(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) + */ + public boolean hasChildren(Object element) { + assert element != null; + + boolean hasChildren = false; + + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode)element; + if (node.type != null && node.type.endsWith("DirNode")) { //$NON-NLS-1$ + if (!node.childrenQueried || node.childrenQueryRunning) { + hasChildren = true; + } else if (node.childrenQueried) { + hasChildren = node.children.size() > 0; + } + } + } + + return hasChildren; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeControl.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeControl.java new file mode 100644 index 000000000..1277bec96 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeControl.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.controls; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.tm.te.tcf.filesystem.internal.nls.Messages; +import org.eclipse.tm.te.ui.interfaces.IUIConstants; +import org.eclipse.tm.te.ui.trees.AbstractTreeControl; +import org.eclipse.ui.IWorkbenchPart; + + +/** + * Target Explorer: File system browser control. + */ +public class FSTreeControl extends AbstractTreeControl { + + /** + * Constructor. + */ + public FSTreeControl() { + super(); + } + + /** + * Constructor. + * + * @param parentPart The parent workbench part this control is embedded in or <code>null</code>. + */ + public FSTreeControl(IWorkbenchPart parentPart) { + super(parentPart); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.trees.AbstractTreeControl#configureTreeViewer(org.eclipse.jface.viewers.TreeViewer) + */ + @Override + protected void configureTreeViewer(TreeViewer viewer) { + super.configureTreeViewer(viewer); + + Tree tree = viewer.getTree(); + if (hasColumns()) { + TreeColumn column = new TreeColumn(tree, SWT.LEFT); + column.setText(Messages.FSTreeControl_column_name_label); + column.setWidth(300); + + column = new TreeColumn(tree, SWT.RIGHT); + column.setText(Messages.FSTreeControl_column_size_label); + column.setWidth(100); + + column = new TreeColumn(tree, SWT.RIGHT); + column.setText(Messages.FSTreeControl_column_modified_label); + column.setWidth(200); + } + tree.setHeaderVisible(hasColumns()); + } + + /** + * Returns if or if not to show the tree columns. + * + * @return <code>True</code> to show the tree columns, <code>false</code> otherwise. + */ + protected boolean hasColumns() { + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.trees.AbstractTreeControl#doCreateTreeViewerContentProvider(org.eclipse.jface.viewers.TreeViewer) + */ + @Override + protected ITreeContentProvider doCreateTreeViewerContentProvider(TreeViewer viewer) { + return new FSTreeContentProvider(); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.trees.AbstractTreeControl#doCreateTreeViewerLabelProvider(org.eclipse.jface.viewers.TreeViewer) + */ + @Override + protected ILabelProvider doCreateTreeViewerLabelProvider(TreeViewer viewer) { + return new FSTreeLabelProvider(viewer); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.trees.AbstractTreeControl#doCreateTreeViewerSelectionChangedListener(org.eclipse.jface.viewers.TreeViewer) + */ + @Override + protected ISelectionChangedListener doCreateTreeViewerSelectionChangedListener(TreeViewer viewer) { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.trees.AbstractTreeControl#doCreateTreeViewerComparator(org.eclipse.jface.viewers.TreeViewer) + */ + @Override + protected ViewerComparator doCreateTreeViewerComparator(TreeViewer viewer) { + return new FSTreeViewerComparator(viewer, (ILabelProvider)viewer.getLabelProvider()); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.trees.AbstractTreeControl#getAutoExpandLevel() + */ + @Override + protected int getAutoExpandLevel() { + return 0; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.trees.AbstractTreeControl#getContextMenuId() + */ + @Override + protected String getContextMenuId() { + return IUIConstants.ID_CONTROL_MENUS_BASE + ".menu.fs"; //$NON-NLS-1$; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeLabelProvider.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeLabelProvider.java new file mode 100644 index 000000000..4c4843fc8 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeLabelProvider.java @@ -0,0 +1,175 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.controls; + +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm.te.tcf.filesystem.activator.UIPlugin; +import org.eclipse.tm.te.tcf.filesystem.internal.registries.InternalImageRegistry; +import org.eclipse.tm.te.ui.nodes.PendingOperation; +import org.eclipse.tm.te.ui.views.interfaces.IUIConstants; +import org.eclipse.ui.IEditorRegistry; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.navigator.CommonNavigator; + + +/** + * Target Explorer: File system tree control label provider implementation. + */ +public class FSTreeLabelProvider extends LabelProvider implements ITableLabelProvider { + private IEditorRegistry fEditorRegistry = null; + + private static final SimpleDateFormat DATE_MODIFIED_FORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm"); //$NON-NLS-1$ + private static final DecimalFormat SIZE_FORMAT = new DecimalFormat(); + + // Reference to the parent tree viewer + private TreeViewer fParentViewer; + + /** + * Constructor. + */ + public FSTreeLabelProvider() { + this(null); + } + + /** + * Constructor. + * + * @param viewer The tree viewer or <code>null</code>. + */ + public FSTreeLabelProvider(TreeViewer viewer) { + super(); + fParentViewer = viewer; + } + + /** + * Returns the parent tree viewer instance. + * + * @return The parent tree viewer or <code>null</code>. + */ + public final TreeViewer getParentViewer() { + if (fParentViewer == null) { + if (PlatformUI.getWorkbench() != null && PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null + && PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() != null) { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IViewPart part = page.findView(IUIConstants.ID_EXPLORER); + if (part instanceof CommonNavigator) { + fParentViewer = ((CommonNavigator)part).getCommonViewer(); + } + } + } + return fParentViewer; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + */ + @Override + public String getText(Object element) { + if (element instanceof FSTreeNode) { + return ((FSTreeNode)element).name; + } + return super.getText(element); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object) + */ + @Override + public Image getImage(Object element) { + if (element != null) { + boolean isExpanded = getParentViewer().getExpandedState(element); + + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode)element; + if ("FSRootDirNode".equals(node.type)) {//$NON-NLS-1$ + return isExpanded ? UIPlugin.getImage(InternalImageRegistry.OBJ_RootDriveOpen) : UIPlugin.getImage(InternalImageRegistry.OBJ_RootDrive); + } else if ("FSDirNode".equals(node.type)) { //$NON-NLS-1$ + return isExpanded ? PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER) : UIPlugin.getImage(InternalImageRegistry.OBJ_Folder); + } else if ("FSFileNode".equals(node.type)) { //$NON-NLS-1$ + String key = node.name; + Image image = UIPlugin.getImage(key); + if (image == null) { + + ImageDescriptor descriptor = getEditorRegistry().getImageDescriptor(key); + if (descriptor == null) descriptor = getEditorRegistry().getSystemExternalEditorImageDescriptor(key); + if (descriptor != null) UIPlugin.getDefault().getImageRegistry().put(key, descriptor); + image = UIPlugin.getImage(key); + } + return image; + } + } + } + + return super.getImage(element); + } + + private IEditorRegistry getEditorRegistry() { + if (fEditorRegistry == null) { + IWorkbench workbench = PlatformUI.getWorkbench(); + if (workbench != null) fEditorRegistry = workbench.getEditorRegistry(); + } + return fEditorRegistry; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int) + */ + public Image getColumnImage(Object element, int columnIndex) { + if (columnIndex == 0) return getImage(element); + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int) + */ + public String getColumnText(Object element, int columnIndex) { + if (columnIndex == 0) return getText(element); + + if (element instanceof PendingOperation) return ""; //$NON-NLS-1$ + + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode)element; + if (node.type != null && node.type.startsWith("FS")) { //$NON-NLS-1$ + boolean isDirNode = node.type.endsWith("DirNode"); //$NON-NLS-1$ + switch (columnIndex) { + case 1: + // Directory nodes does not have a size + if (!isDirNode) { + if (node.attr != null) { + return SIZE_FORMAT.format(node.attr.size / 1024) + " KB"; //$NON-NLS-1$ + } + } + break; + case 2: + if (node.attr != null) { + return DATE_MODIFIED_FORMAT.format(new Date(node.attr.mtime)); + } + break; + } + + } + } + + return ""; //$NON-NLS-1$ + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeNode.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeNode.java new file mode 100644 index 000000000..07bc2b842 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeNode.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.controls; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.tm.tcf.services.IFileSystem; + +/** + * Target Explorer: Representation of a file system tree node. + */ +public final class FSTreeNode extends PlatformObject { + private final UUID fUniqueId = UUID.randomUUID(); + + /** + * The tree node name. + */ + public String name = null; + + /** + * The tree node type. + */ + public String type = null; + + /** + * The tree node file system attributes + */ + public IFileSystem.FileAttrs attr = null; + + /** + * The tree node parent. + */ + public FSTreeNode parent = null; + + /** + * The tree node children. + */ + public List<FSTreeNode> children = new ArrayList<FSTreeNode>(); + + /** + * Flag to mark once the children of the node got queried + */ + public boolean childrenQueried = false; + + /** + * Flag to mark once the children query is running + */ + public boolean childrenQueryRunning = false; + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public final int hashCode() { + return fUniqueId.hashCode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public final boolean equals(Object obj) { + if (obj instanceof FSTreeNode) { + return fUniqueId.equals(((FSTreeNode)obj).fUniqueId); + } + return super.equals(obj); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return name != null ? name : super.toString(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeViewerComparator.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeViewerComparator.java new file mode 100644 index 000000000..071574c4a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeViewerComparator.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.controls; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.tm.te.ui.trees.TreeViewerComparator; + + +/** + * Target Explorer: File system tree control viewer comparator implementation. + */ +public class FSTreeViewerComparator extends TreeViewerComparator { + + /** + * Constructor. + * + * @param viewer The parent viewer. Must be not <code>null</code>. + * @param labelProvider The label provider. Must be not <code>null</code>. + */ + public FSTreeViewerComparator(Viewer viewer, ILabelProvider labelProvider) { + super(viewer, labelProvider); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.trees.TreeViewerComparator#doCompare(java.lang.Object, java.lang.Object, java.lang.String, int, int) + */ + @Override + protected int doCompare(Object node1, Object node2, String sortColumn, int index, int inverter) { + if (node1 instanceof FSTreeNode && node2 instanceof FSTreeNode) { + // Get the type labels + String t1 = ((FSTreeNode)node1).type; + String t2 = ((FSTreeNode)node2).type; + + // Group directories and files always together before sorting by name + if (("FSRootDirNode".equals(t1) || "FSDirNode".equals(t1)) //$NON-NLS-1$ //$NON-NLS-2$ + && !("FSRootDirNode".equals(t2) || "FSDirNode".equals(t2))) { //$NON-NLS-1$ //$NON-NLS-2$ + return -1 * inverter; + } + + if (("FSRootDirNode".equals(t2) || "FSDirNode".equals(t2)) //$NON-NLS-1$ //$NON-NLS-2$ + && !("FSRootDirNode".equals(t1) || "FSDirNode".equals(t1))) { //$NON-NLS-1$ //$NON-NLS-2$ + return 1 * inverter; + } + + // If the nodes are of the same type and one entry starts + // with a '.', it comes before the one without a '.' + if (t1 != null && t2 != null && t1.equals(t2)) { + String n1 = doGetText(node1, index); + String n2 = doGetText(node2, index); + if (n1 != null && n2 != null) { + if (n1.startsWith(".") && !n2.startsWith(".")) return -1 * inverter; //$NON-NLS-1$ //$NON-NLS-2$ + if (!n1.startsWith(".") && n2.startsWith(".")) return 1 * inverter; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + } + + return super.doCompare(node1, node2, sortColumn, index, inverter); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeViewerSorter.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeViewerSorter.java new file mode 100644 index 000000000..24715fc77 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/controls/FSTreeViewerSorter.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.controls; + +import org.eclipse.jface.viewers.TreePathViewerSorter; +import org.eclipse.jface.viewers.Viewer; + +/** + * Target Explorer: File system tree control viewer sorter implementation. + */ +public class FSTreeViewerSorter extends TreePathViewerSorter { + private final FSTreeLabelProvider fLabelProvider = new FSTreeLabelProvider(); + private final FSTreeViewerComparator fComparator; + + /** + * Constructor. + */ + public FSTreeViewerSorter() { + fComparator = new FSTreeViewerComparator(fLabelProvider.getParentViewer(), fLabelProvider); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + return fComparator.compare(viewer, e1, e2); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/dialogs/FSOpenFileDialog.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/dialogs/FSOpenFileDialog.java new file mode 100644 index 000000000..d587963a6 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/dialogs/FSOpenFileDialog.java @@ -0,0 +1,198 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.dialogs; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.te.tcf.filesystem.controls.FSTreeControl; +import org.eclipse.tm.te.tcf.filesystem.internal.nls.Messages; +import org.eclipse.tm.te.ui.dialogs.CustomTrayDialog; +import org.eclipse.tm.te.ui.forms.CustomFormToolkit; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.editor.IFormPage; +import org.eclipse.ui.forms.widgets.FormToolkit; + + +/** + * Target Explorer: File system open file dialog. + */ +public class FSOpenFileDialog extends CustomTrayDialog { + // Reference to the subcontrol + private final FSTreeControl fControl; + // Reference to the current selection within the file system tree + private ISelection fSelection; + + protected class FSOpenFileTreeControl extends FSTreeControl { + + /** + * Constructor. + */ + public FSOpenFileTreeControl() { + super(); + } + + /** + * Constructor. + * + * @param parentPage The parent form page this control is embedded in or + * <code>null</code> if the control is not embedded within + * a form page. + */ + public FSOpenFileTreeControl(FormPage parentPage) { + super(parentPage); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.tcf.ui.internal.controls.trees.fs.FSTreeControl#hasColumns() + */ + @Override + protected boolean hasColumns() { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.tcf.ui.internal.controls.trees.fs.FSTreeControl#doCreateTreeViewerSelectionChangedListener(org.eclipse.jface.viewers.TreeViewer) + */ + @Override + protected ISelectionChangedListener doCreateTreeViewerSelectionChangedListener(TreeViewer viewer) { + return new FSOpenFileTreeControlSelectionChangedListener(); + } + } + + protected class FSOpenFileTreeControlSelectionChangedListener implements ISelectionChangedListener{ + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) + */ + @SuppressWarnings("synthetic-access") + public void selectionChanged(SelectionChangedEvent event) { + fSelection = event.getSelection(); + updateButtons(); + } + } + + /** + * Constructor. + * + * @param shell The parent shell or <code>null</code>. + */ + public FSOpenFileDialog(Shell shell) { + this(shell, null); + } + + /** + * Constructor. + * + * @param shell The parent shell or <code>null</code>. + * @param contextHelpId The dialog context help id or <code>null</code>. + */ + public FSOpenFileDialog(Shell shell, String contextHelpId) { + this(null, shell, contextHelpId); + } + + /** + * Constructor. + * + * @param parentPage The parent form page this control is embedded in or + * <code>null</code> if the control is not embedded within + * a form page. + * @param shell The parent shell or <code>null</code>. + * @param contextHelpId The dialog context help id or <code>null</code>. + */ + public FSOpenFileDialog(FormPage parentPage, Shell shell, String contextHelpId) { + super(shell, contextHelpId); + + fControl = new FSOpenFileTreeControl(parentPage); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#isResizable() + */ + @Override + protected boolean isResizable() { + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.ide.common.ui.dialogs.WRUnifiedTrayDialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + + setDialogTitle(Messages.FSOpenFileDialog_title); + + Composite panel = new Composite(composite, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; layout.marginHeight = 0; + panel.setLayout(layout); + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + layoutData.heightHint = convertHeightInCharsToPixels(25); + layoutData.widthHint = convertWidthInCharsToPixels(50); + panel.setLayoutData(layoutData); + + CustomFormToolkit toolkit = null; + if (fControl.getParentPart() instanceof IFormPage && ((IFormPage)fControl.getParentPart()).getManagedForm() != null) { + toolkit = new CustomFormToolkit(((IFormPage)fControl.getParentPart()).getManagedForm().getToolkit()); + } + if (toolkit == null) toolkit = new CustomFormToolkit(new FormToolkit(getShell().getDisplay())); + + fControl.setupFormPanel(panel, toolkit); + + return composite; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.ide.common.ui.dialogs.WRUnifiedTrayDialog#close() + */ + @Override + public boolean close() { + if (fControl != null) { + fControl.dispose(); + } + + return super.close(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createButtonBar(Composite parent) { + Control control = super.createButtonBar(parent); + updateButtons(); + return control; + } + + /** + * Update the button enablement. + */ + protected void updateButtons() { + Button okButton = getButton(IDialogConstants.OK_ID); + if (okButton != null) okButton.setEnabled(fSelection != null && !fSelection.isEmpty()); + } + + /** + * Returns the current file system control selection. + * @return + */ + public ISelection getSelection() { + return fSelection; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/explorer/FSExplorerEditorPage.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/explorer/FSExplorerEditorPage.java new file mode 100644 index 000000000..f3e361f11 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/explorer/FSExplorerEditorPage.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.internal.explorer; + +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tm.te.tcf.filesystem.controls.FSTreeControl; +import org.eclipse.tm.te.tcf.filesystem.internal.help.IContextHelpIds; +import org.eclipse.tm.te.tcf.filesystem.internal.nls.Messages; +import org.eclipse.tm.te.ui.forms.CustomFormToolkit; +import org.eclipse.tm.te.ui.views.editor.AbstractEditorPage; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.widgets.ExpandableComposite; +import org.eclipse.ui.forms.widgets.Section; +import org.eclipse.ui.forms.widgets.TableWrapData; + + +/** + * Target Explorer: File system editor page implementation. + * + * @author uwe.stieber@windriver.com + */ +public class FSExplorerEditorPage extends AbstractEditorPage { + // The references to the pages subcontrol's (needed for disposal) + private FSTreeControl fFileSystemControl; + + // Reference to the form toolkit instance + private CustomFormToolkit fToolkit = null; + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.editor.FormPage#dispose() + */ + @Override + public void dispose() { + if (fFileSystemControl != null) { fFileSystemControl.dispose(); fFileSystemControl = null; } + super.dispose(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.editor.FormPage#createFormContent(org.eclipse.ui.forms.IManagedForm) + */ + @Override + protected void createFormContent(IManagedForm managedForm) { + // Configure the managed form + configureManagedForm(managedForm); + + // Get the form body + Composite body = managedForm.getForm().getBody(); + + // Create the toolkit instance + fToolkit = new CustomFormToolkit(managedForm.getToolkit()); + + // Do create the content of the form now + doCreateFormContent(body, fToolkit); + + // Re-arrange the controls + managedForm.reflow(true); + } + + /** + * Configure the managed form to be ready for usage. + * + * @param managedForm The managed form. Must be not <code>null</code>. + */ + protected void configureManagedForm(IManagedForm managedForm) { + assert managedForm != null; + + // Configure main layout + Composite body = managedForm.getForm().getBody(); + GridLayout layout = new GridLayout(); + layout.marginHeight = 2; layout.marginWidth = 0; + body.setLayout(layout); + body.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); + + // Set context help id + PlatformUI.getWorkbench().getHelpSystem().setHelp(managedForm.getForm(), IContextHelpIds.FS_EXPLORER_EDITOR_PAGE); + } + + /** + * Do create the managed form content. + * + * @param parent The parent composite. Must be not <code>null</code> + * @param toolkit The {@link CustomFormToolkit} instance. Must be not <code>null</code>. + */ + protected void doCreateFormContent(Composite parent, CustomFormToolkit toolkit) { + assert parent != null && toolkit != null; + + Section section = toolkit.getFormToolkit().createSection(parent, ExpandableComposite.TITLE_BAR); + String title = Messages.FSExplorerTreeControl_section_title; + // Stretch to a length of 40 characters to make sure the title can be changed + // to hold and show text up to this length + while (title.length() < 40) { + title += " "; //$NON-NLS-1$ + } + // Set the title to the section + section.setText(title); + section.setLayoutData(new GridData(GridData.FILL_BOTH)); + + // Create the client area + Composite client = toolkit.getFormToolkit().createComposite(section); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; layout.marginHeight = 0; + client.setLayout(layout); + section.setClient(client); + + // Setup the file system tree control + fFileSystemControl = doCreateFileSystemTreeControl(); + assert fFileSystemControl != null; + fFileSystemControl.setupFormPanel((Composite)section.getClient(), toolkit); + + // Set the initial input + fFileSystemControl.getViewer().setInput(getEditorInputNode()); + } + + /** + * Creates and returns a file system tree control. + * + * @return The new file system tree control. + */ + protected FSTreeControl doCreateFileSystemTreeControl() { + return new FSTreeControl(this); + } + + /** + * Returns the associated file system tree control. + * + * @return The associated file system tree control or <code>null</code>. + */ + protected final FSTreeControl getFileSystemTreeControl() { + return fFileSystemControl; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/help/IContextHelpIds.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/help/IContextHelpIds.java new file mode 100644 index 000000000..be7f94bb4 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/help/IContextHelpIds.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.internal.help; + +import org.eclipse.tm.te.tcf.filesystem.activator.UIPlugin; + +/** + * Plugin context help id definitions. + */ +public interface IContextHelpIds { + + /** + * Target Explorer file system UI plug-in common context help id prefix. + */ + public final static String PREFIX = UIPlugin.getUniqueIdentifier() + "."; //$NON-NLS-1$ + + /** + /** + * Target Explorer details editor page: File system explorer + */ + public final static String FS_EXPLORER_EDITOR_PAGE = PREFIX + "FSExplorerEditorPage"; //$NON-NLS-1$ +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/nls/Messages.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/nls/Messages.java new file mode 100644 index 000000000..956484609 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/nls/Messages.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.internal.nls; + +import java.lang.reflect.Field; + +import org.eclipse.osgi.util.NLS; + +/** + * Target Explorer: File System plug-in externalized strings management. + */ +public class Messages extends NLS { + + // The plug-in resource bundle name + private static final String BUNDLE_NAME = "org.eclipse.tm.te.tcf.filesystem.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 FSExplorerTreeControl_section_title; + + public static String FSTreeControl_column_name_label; + public static String FSTreeControl_column_size_label; + public static String FSTreeControl_column_modified_label; + + public static String FSOpenFileDialog_title; +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/nls/Messages.properties new file mode 100644 index 000000000..7531e40ce --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/nls/Messages.properties @@ -0,0 +1,12 @@ +# +# org.eclipse.tm.te.tcf.filesystem +# Externalized Strings. +# + +FSExplorerTreeControl_section_title=Exploring File System + +FSTreeControl_column_name_label=Name +FSTreeControl_column_size_label=Size +FSTreeControl_column_modified_label=Date Modified + +FSOpenFileDialog_title=Select Process Image diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/registries/InternalImageRegistry.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/registries/InternalImageRegistry.java new file mode 100644 index 000000000..0ea23ad5b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.filesystem/src/org/eclipse/tm/te/tcf/filesystem/internal/registries/InternalImageRegistry.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.filesystem.internal.registries; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.Plugin; +import org.eclipse.tm.te.ui.images.AbstractImageRegistry; + + +/** + * Target Explorer: File System UI Plug-in image registry. + */ +public class InternalImageRegistry extends AbstractImageRegistry { + private static List<Object[]> fStore = new ArrayList<Object[]>(); + + // declare all keys down here + public static final String OBJ_RootDrive = declareLocalImage("obj16", "rootdrive.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String OBJ_RootDriveOpen = declareLocalImage("obj16", "rootdriveopen.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String OBJ_Folder = declareLocalImage("obj16", "folder.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + + // external eclipse icons not reachable using ISharedImages + + /** + * Constructor. + * + * @param plugin The plugin descriptor the image registry is created for. + */ + public InternalImageRegistry(Plugin plugin) { + super(plugin); + } + + /** + * Initialize image registry with all keys known yet. + */ + public void initialize() { + for (Iterator<Object[]> iter = fStore.iterator(); iter.hasNext();) { + Object[] element = iter.next(); + if (element.length == 3) { + localImage((String)element[0], (String)element[1], (String)element[2]); + } + else if (element.length > 3){ + externalImage((String)element[0], (String)element[1], (String[])element[2], (String)element[3]); + } + } + } + + /** + * Declare a locally stored image to the image registry. + */ + static String declareLocalImage(String dir, String name) { + List<Object> registryObject = new ArrayList<Object>(); + registryObject.add(dir); + registryObject.add(name); + String key = name + "_" + registryObject.hashCode(); //$NON-NLS-1$ + registryObject.add(0, key); + fStore.add(registryObject.toArray()); + return key; + } + + /** + * Declare a externally stored image to the image registry. + */ + static String declareExternalImage(String plugin, String[] dirs, String name) { + List<Object> registryObject = new ArrayList<Object>(); + registryObject.add(plugin); + registryObject.add(dirs); + registryObject.add(name); + String key = name + "_" + registryObject.hashCode(); //$NON-NLS-1$ + registryObject.add(0, key); + fStore.add(registryObject.toArray()); + return key; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/.classpath b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/.classpath new file mode 100644 index 000000000..64c5e31b7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.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/J2SE-1.5"/> + <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.tm.te.tcf.locator/.project b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/.project new file mode 100644 index 000000000..1588cf8cc --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.tm.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> +</projectDescription> diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/.settings/org.eclipse.jdt.core.prefs b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..4b09f4879 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,77 @@ +#Wed Apr 06 16:34:47 CEST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +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=error +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.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=ignore +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=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +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.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.5 diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/META-INF/MANIFEST.MF new file mode 100644 index 000000000..0b6fddbed --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/META-INF/MANIFEST.MF @@ -0,0 +1,23 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.tm.te.tcf.locator; singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.tm.te.tcf.locator.activator.CoreBundleActivator +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0", + org.eclipse.core.expressions;bundle-version="3.4.200", + org.eclipse.tm.tcf.core;bundle-version="0.3.0", + org.eclipse.tm.te.tcf.core;bundle-version="1.0.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.tm.te.tcf.locator;version="1.0.0", + org.eclipse.tm.te.tcf.locator.interfaces;version="1.0.0", + org.eclipse.tm.te.tcf.locator.interfaces.nodes;version="1.0.0", + org.eclipse.tm.te.tcf.locator.interfaces.preferences;version="1.0.0", + org.eclipse.tm.te.tcf.locator.interfaces.services;version="1.0.0", + org.eclipse.tm.te.tcf.locator.listener;version="1.0.0", + org.eclipse.tm.te.tcf.locator.nodes;version="1.0.0", + org.eclipse.tm.te.tcf.locator.services;version="1.0.0", + org.eclipse.tm.te.tcf.locator.utils;version="1.0.0" diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/build.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/build.properties new file mode 100644 index 000000000..30b2fc40b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.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.tm.te.tcf.locator/plugin.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/plugin.properties new file mode 100644 index 000000000..b6f6fe9dd --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.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: +# Uwe Stieber (Wind River) - initial API and implementation +################################################################################## + +pluginName = Target Explorer, TCF Locator Extensions +providerName = Eclipse.org diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/plugin.xml b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/plugin.xml new file mode 100644 index 000000000..b748d8e90 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/plugin.xml @@ -0,0 +1,23 @@ +<?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.tm.te.tcf.locator.internal.preferences.PreferencesInitializer"> + </initializer> + </extension> + +<!-- Eclipse core expressions property tester --> + <extension point="org.eclipse.core.expressions.propertyTesters"> + <propertyTester + class="org.eclipse.tm.te.tcf.locator.internal.MyPropertyTester" + id="org.eclipse.tm.te.tcf.locator.LocatorModelPropertyTester" + namespace="org.eclipse.tm.te.tcf.locator" + properties="name,hasLocalService,hasRemoteService" + type="org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel"> + </propertyTester> + </extension> + +</plugin> diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/Scanner.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/Scanner.java new file mode 100644 index 000000000..9466baa0c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/Scanner.java @@ -0,0 +1,151 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +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.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.locator.interfaces.IScanner; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.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 fParentModel; + + // Reference to the scanner configuration + private final Map<String, Object> fConfiguration = new HashMap<String, Object>(); + + // Flag to mark if the scanner is terminated + private AtomicBoolean fTerminated = new AtomicBoolean(false); + + /** + * Constructor. + * + * @param parentModel The parent model instance. Must be not <code>null</code>. + */ + public Scanner(ILocatorModel parentModel) { + super(Scanner.class.getName()); + assert parentModel != null; + fParentModel = parentModel; + } + + /** + * Returns the parent model instance. + * + * @return The parent model instance. + */ + protected ILocatorModel getParentModel() { + return fParentModel; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.IScanner#setConfiguration(java.util.Map) + */ + public void setConfiguration(Map<String, Object> configuration) { + assert configuration != null; + fConfiguration.clear(); + fConfiguration.putAll(configuration); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.IScanner#getConfiguration() + */ + public Map<String, Object> getConfiguration() { + return fConfiguration; + } + + /* (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() { + 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() { + 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.tm.te.tcf.locator.core.interfaces.IScanner#terminate() + */ + public void terminate() { + fTerminated.set(true); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.IScanner#isTerminated() + */ + public final boolean isTerminated() { + return fTerminated.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.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/ScannerRunnable.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/ScannerRunnable.java new file mode 100644 index 000000000..286d878d4 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/ScannerRunnable.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator; + +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import org.eclipse.tm.tcf.core.ChannelTCP; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.ILocator; +import org.eclipse.tm.te.tcf.locator.interfaces.IScanner; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModelProperties; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelLookupService; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelUpdateService; +import org.eclipse.tm.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 fParentScanner; + // Reference to the peer model node to update + private final IPeerModel fPeerNode; + // Reference to the channel + private IChannel fChannel = 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 be not <code>null</code>. + */ + public ScannerRunnable(IScanner scanner, IPeerModel peerNode) { + super(); + + fParentScanner = scanner; + + assert peerNode != null; + fPeerNode = peerNode; + } + + /** + * Returns the parent scanner instance. + * + * @return The parent scanner instance or <code>null</code>. + */ + protected final IScanner getParentScanner() { + return fParentScanner; + } + + /* (non-Javadoc) + * @see java.lang.Runnable#run() + */ + public void run() { + if (fPeerNode != null && fPeerNode.getPeer() != null) { + // Open the channel + fChannel = fPeerNode.getPeer().openChannel(); + // Configure the connect timeout + if (fChannel instanceof ChannelTCP) { + int timeout = fPeerNode.getIntProperty(IPeerModelProperties.PROP_CONNECT_TIMEOUT); + if (timeout == -1) timeout = DEFAULT_SOCKET_CONNECT_TIMEOUT; + ((ChannelTCP)fChannel).setConnectTimeout(timeout); + } + // Add ourself as channel listener + fChannel.addChannelListener(this); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.protocol.IChannel.IChannelListener#onChannelOpened() + */ + public void onChannelOpened() { + // Peer is reachable + if (fChannel != null) { + // Remove ourself as channel listener + fChannel.removeChannelListener(this); + } + + // Set the peer state property + if (fPeerNode != null) { + int counter = fPeerNode.getIntProperty(IPeerModelProperties.PROP_CHANNEL_REF_COUNTER); + fPeerNode.setProperty(IPeerModelProperties.PROP_STATE, counter > 0 ? IPeerModelProperties.STATE_CONNECTED : IPeerModelProperties.STATE_REACHABLE); + fPeerNode.setProperty(IPeerModelProperties.PROP_LAST_SCANNER_ERROR, null); + } + + if (fChannel != null && fChannel.getState() == IChannel.STATE_OPEN) { + // Get the parent model from the model mode + final ILocatorModel model = (ILocatorModel)fPeerNode.getAdapter(ILocatorModel.class); + if (model != null) { + // Get the local service + Collection<String> localServices = new ArrayList<String>(fChannel.getLocalServices()); + // Get the remote services + Collection<String> remoteServices = new ArrayList<String>(fChannel.getRemoteServices()); + + // Get the update service + ILocatorModelUpdateService updateService = model.getService(ILocatorModelUpdateService.class); + if (updateService != null) { + // Update the services nodes + updateService.updatePeerServices(fPeerNode, localServices, remoteServices); + } + + // Use the open channel to ask the remote peer what other + // peers it knows + ILocator locator = fChannel.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() { + 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 + fChannel.close(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.protocol.IChannel.IChannelListener#onChannelClosed(java.lang.Throwable) + */ + public void onChannelClosed(Throwable error) { + // Peer is not reachable + + if (fChannel != null) { + // Remove ourself as channel listener + fChannel.removeChannelListener(this); + } + + // Set the peer state property, if the scanner the runnable + // has been scheduled from is still active. + if (fPeerNode != null && (fParentScanner == null || fParentScanner != null && !fParentScanner.isTerminated())) { + fPeerNode.setProperty(IPeerModelProperties.PROP_CHANNEL_REF_COUNTER, null); + fPeerNode.setProperty(IPeerModelProperties.PROP_STATE, + error instanceof SocketTimeoutException ? IPeerModelProperties.STATE_NOT_REACHABLE : IPeerModelProperties.STATE_ERROR); + fPeerNode.setProperty(IPeerModelProperties.PROP_LAST_SCANNER_ERROR, error instanceof SocketTimeoutException ? null : error); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.protocol.IChannel.IChannelListener#congestionLevel(int) + */ + public void congestionLevel(int level) { + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/activator/CoreBundleActivator.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/activator/CoreBundleActivator.java new file mode 100644 index 000000000..d6426c304 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/activator/CoreBundleActivator.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.activator; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class CoreBundleActivator implements BundleActivator { + // The bundle context + private static BundleContext context; + + /** + * Returns the bundle context + * + * @return the bundle context + */ + public static BundleContext getContext() { + return context; + } + + /** + * Convenience method which returns the unique identifier of this plugin. + */ + public static String getUniqueIdentifier() { + if (getContext() != null && getContext().getBundle() != null) { + return getContext().getBundle().getSymbolicName(); + } + return null; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext bundleContext) throws Exception { + CoreBundleActivator.context = bundleContext; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception { + CoreBundleActivator.context = null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/IModelListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/IModelListener.java new file mode 100644 index 000000000..32ebc923d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.interfaces; + +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.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.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/IScanner.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/IScanner.java new file mode 100644 index 000000000..4499f107f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.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 be not <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.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/nodes/ILocatorModel.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/nodes/ILocatorModel.java new file mode 100644 index 000000000..eef07852d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.interfaces.nodes; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.tm.tcf.services.ILocator; +import org.eclipse.tm.te.tcf.locator.interfaces.IModelListener; +import org.eclipse.tm.te.tcf.locator.interfaces.IScanner; +import org.eclipse.tm.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 be not <code>null</code>. + */ + public void addListener(IModelListener listener); + + /** + * Removes the specified listener from the list of model listener. + * + * @param listener The listener. Must be not <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 be not <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 be not <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.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/nodes/IPeerModel.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/nodes/IPeerModel.java new file mode 100644 index 000000000..a1569db6b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/nodes/IPeerModel.java @@ -0,0 +1,288 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.interfaces.nodes; + +import java.util.Map; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.tm.tcf.protocol.IPeer; + +/** + * 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 IAdaptable { + + /** + * 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(); + + /** + * Set the properties from the given map. Calling this method + * will overwrite all previous set properties. + * + * @param properties The map of properties to set. Must be not <code>null</code>. + */ + public void setProperties(Map<String, Object> properties); + + /** + * Stores the property under the given property key using the given property value. + * If the current property value is equal to the given property value, no store + * operation will be executed. If the property value is not <code>null</code> and + * is different from the current property value, the new value will be written to + * the property store and a property change event is fired. If the property value + * is <code>null</code>, the property key and the currently stored value are removed + * from the property store. + * + * + * @param key The property key. Must be not <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + */ + public boolean setProperty(String key, Object value); + + /** + * Stores the property under the given property key using the given long + * property value. The given long value is transformed to an <code>Long</code> + * object and stored to the properties store via <code>setProperty(java.lang.String, java.lang.Object)</code>. + * + * @param key The property key. Must be not <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + * + * @see <code>setProperty(java.lang.String, java.lang.Object)</code> + */ + public boolean setProperty(String key, long value); + + /** + * Stores the property under the given property key using the given integer + * property value. The given integer value is transformed to an <code>Integer</code> + * object and stored to the properties store via <code>setProperty(java.lang.String, java.lang.Object)</code>. + * + * @param key The property key. Must be not <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + * + * @see <code>setProperty(java.lang.String, java.lang.Object)</code> + */ + public boolean setProperty(String key, int value); + + /** + * Stores the property under the given property key using the given boolean + * property value. The given boolean value is transformed to an <code>Boolean</code> + * object and stored to the properties store via <code>setProperty(java.lang.String, java.lang.Object)</code>. + * + * @param key The property key. Must be not <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + * + * @see <code>setProperty(java.lang.String, java.lang.Object)</code> + */ + public boolean setProperty(String key, boolean value); + + /** + * Stores the property under the given property key using the given float + * property value. The given float value is transformed to an <code>Float</code> + * object and stored to the properties store via <code>setProperty(java.lang.String, java.lang.Object)</code>. + * + * @param key The property key. Must be not <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + * + * @see <code>setProperty(java.lang.String, java.lang.Object)</code> + */ + public boolean setProperty(String key, float value); + + /** + * Stores the property under the given property key using the given double + * property value. The given double value is transformed to an <code>Double</code> + * object and stored to the properties store via <code>setProperty(java.lang.String, java.lang.Object)</code>. + * + * @param key The property key. Must be not <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + * + * @see <code>setProperty(java.lang.String, java.lang.Object)</code> + */ + public boolean setProperty(String key, double value); + + /** + * Return all properties. The result map is read-only. + * + * @return A map containing all properties. + */ + public Map<String, Object> getProperties(); + + /** + * Queries the property value stored under the given property key. If the property + * does not exist, <code>null</code> is returned. + * + * @param key The property key. Must be not <code>null</code>! + * @return The stored property value or <code>null</code>. + */ + public Object getProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.String</code>, the property value casted to + * <code>java.lang.String</code> is returned. In all other cases, <code>null</code> + * is returned. + * + * @param key The property key. Must be not <code>null</code>! + * @return The stored property value casted <code>java.lang.String</code> or <code>null</code>. + */ + public String getStringProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.Long</code>, the property value converted + * to an long value is returned. In all other cases, <code>-1</code> is returned. + * + * @param key The property key. Must be not <code>null</code>! + * @return The stored property value converted to a long value or <code>-1</code>. + */ + public long getLongProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.Integer</code>, the property value converted + * to an integer value is returned. In all other cases, <code>-1</code> is returned. + * + * @param key The property key. Must be not <code>null</code>! + * @return The stored property value converted to an integer value or <code>-1</code>. + */ + public int getIntProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.Boolean</code>, the property value converted + * to an boolean value is returned. In all other cases, <code>false</code> is returned. + * + * @param key The property key. Must be not <code>null</code>! + * @return The stored property value converted to an boolean value or <code>false</code>. + */ + public boolean getBooleanProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.Float</code>, the property value converted + * to an float value is returned. In all other cases, <code>Float.NaN</code> is returned. + * + * @param key The property key. Must be not <code>null</code>! + * @return The stored property value converted to a float value or <code>Float.NaN</code>. + */ + public float getFloatProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.Double</code>, the property value converted + * to an double value is returned. In all other cases, <code>Double.NaN</code> is returned. + * + * @param key The property key. Must be not <code>null</code>! + * @return The stored property value converted to a double value or <code>Double.NaN</code>. + */ + public double getDoubleProperty(String key); + + /** + * Remove all properties from the properties store. The method does not fire any + * properties changed event. + */ + public void clearProperties(); + + /** + * Test if the property value stored under the given property is equal ignoring the case to the given + * expected string value. + * + * @param key The property key. Must be not <code>null</code>. + * @param value The expected property string value. + * @return <code>true</code> if the expected string value is equal ignoring the case to the stored property value, <code>false</code> otherwise. + */ + public boolean isPropertyIgnoreCase(String key, String value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must be not <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, Object value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must be not <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, long value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must be not <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, int value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must be not <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, boolean value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must be not <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, float value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must be not <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, double value); +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/nodes/IPeerModelProperties.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/nodes/IPeerModelProperties.java new file mode 100644 index 000000000..f54cd80ec --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.interfaces.nodes; + +import org.eclipse.tm.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.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/preferences/IPreferenceKeys.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/preferences/IPreferenceKeys.java new file mode 100644 index 000000000..d4a5e24c8 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/preferences/IPreferenceKeys.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.interfaces.preferences; + +/** + * 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$ +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/services/ILocatorModelLookupService.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/services/ILocatorModelLookupService.java new file mode 100644 index 000000000..29216f813 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/services/ILocatorModelLookupService.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.interfaces.services; + +import org.eclipse.tm.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 be not <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 the peer model for the given peer id. + * + * @param agentId The agent id. Must be not <code>null</code>. + * @return The peer model instance, or <code>null</code> if the peer model cannot be found. + */ + public IPeerModel lkupPeerModelByAgentId(String agentId); +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/services/ILocatorModelRefreshService.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/services/ILocatorModelRefreshService.java new file mode 100644 index 000000000..9f430206f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.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.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/services/ILocatorModelService.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/services/ILocatorModelService.java new file mode 100644 index 000000000..d82da4f01 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.interfaces.services; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.tm.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.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/services/ILocatorModelUpdateService.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/interfaces/services/ILocatorModelUpdateService.java new file mode 100644 index 000000000..c1df5932d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.interfaces.services; + +import java.util.Collection; + +import org.eclipse.tm.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 be not <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 be not <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 be not <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.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/MyPropertyTester.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/MyPropertyTester.java new file mode 100644 index 000000000..0869d4c13 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/MyPropertyTester.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.internal; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModelProperties; + + + +/** + * Locator model property tester. + * + * @author uwe.stieber@windriver.com + */ +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) + */ + 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() { + 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 Protocol.isDispatchThread() && node != null; + + 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; + } + } + } + } + + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/nls/Messages.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/nls/Messages.java new file mode 100644 index 000000000..71a99e328 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/nls/Messages.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.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.tm.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 ***** + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/nls/Messages.properties new file mode 100644 index 000000000..5f3b5dc7e --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/nls/Messages.properties @@ -0,0 +1,4 @@ +# +# org.eclipse.tm.te.tcf.locator +# Externalized Strings. +# diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/preferences/PreferencesInitializer.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/internal/preferences/PreferencesInitializer.java new file mode 100644 index 000000000..c0312f5ec --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.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.tm.te.tcf.locator.activator.CoreBundleActivator; +import org.eclipse.tm.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 = new DefaultScope().getNode(CoreBundleActivator.getUniqueIdentifier()); + if (prefs != null) { + // Filtered by agent id: default on + prefs.putBoolean(IPreferenceKeys.PREF_FILTER_BY_AGENT_ID, true); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/listener/ChannelStateChangeListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/listener/ChannelStateChangeListener.java new file mode 100644 index 000000000..99353b7d6 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/listener/ChannelStateChangeListener.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.listener; + +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.core.interfaces.listeners.IChannelStateChangeListener; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModelProperties; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelLookupService; + + +/** + * Channel state change listener implementation. + */ +public class ChannelStateChangeListener implements IChannelStateChangeListener { + // Reference to the parent model + private final ILocatorModel fModel; + + /** + * Constructor. + * + * @param model The parent locator model. Must be not <code>null</code>. + */ + public ChannelStateChangeListener(ILocatorModel model) { + assert model != null; + fModel = model; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.tcf.core.interfaces.listeners.IChannelStateChangeListener#stateChanged(org.eclipse.tm.tcf.protocol.IChannel, int) + */ + public void stateChanged(IChannel channel, int state) { + assert Protocol.isDispatchThread() && channel != null; + + switch (state) { + case IChannel.STATE_OPEN: + IPeer peer = channel.getRemotePeer(); + // Find the corresponding model node + IPeerModel node = fModel.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 = fModel.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.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/listener/LocatorListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/listener/LocatorListener.java new file mode 100644 index 000000000..bdf0605ef --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/listener/LocatorListener.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.listener; + +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.ILocator; +import org.eclipse.tm.te.tcf.locator.ScannerRunnable; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModelProperties; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelLookupService; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelUpdateService; +import org.eclipse.tm.te.tcf.locator.nodes.PeerModel; + + +/** + * Locator listener implementation. + */ +public class LocatorListener implements ILocator.LocatorListener { + // Reference to the parent model + private final ILocatorModel fModel; + + /** + * Constructor. + * + * @param model The parent locator model. Must be not <code>null</code>. + */ + public LocatorListener(ILocatorModel model) { + super(); + + assert model != null; + fModel = model; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.services.ILocator.LocatorListener#peerAdded(org.eclipse.tm.tcf.protocol.IPeer) + */ + public void peerAdded(IPeer peer) { + if (fModel != null && peer != null) { + // find the corresponding model node to remove (expected to be null) + IPeerModel peerNode = fModel.getService(ILocatorModelLookupService.class).lkupPeerModelById(peer.getID()); + // If found, remove the old node + if (peerNode != null) fModel.getService(ILocatorModelUpdateService.class).remove(peerNode); + // Create a new peer node instance + peerNode = new PeerModel(fModel, peer); + // Validate the peer node before adding + if (peerNode != null) peerNode = fModel.validatePeerNodeForAdd(peerNode); + // Add the peer node to the model + if (peerNode != null) { + fModel.getService(ILocatorModelUpdateService.class).add(peerNode); + // And schedule for immediate status update + Runnable runnable = new ScannerRunnable(fModel.getScanner(), peerNode); + Protocol.invokeLater(runnable); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.services.ILocator.LocatorListener#peerChanged(org.eclipse.tm.tcf.protocol.IPeer) + */ + public void peerChanged(IPeer peer) { + if (fModel != null && peer != null) { + // find the corresponding model node to remove + IPeerModel peerNode = fModel.getService(ILocatorModelLookupService.class).lkupPeerModelById(peer.getID()); + // Update the peer instance + if (peerNode != null) peerNode.setProperty(IPeerModelProperties.PROP_INSTANCE, peer); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.services.ILocator.LocatorListener#peerRemoved(java.lang.String) + */ + public void peerRemoved(String id) { + if (fModel != null && id != null) { + // find the corresponding model node to remove + IPeerModel peerNode = fModel.getService(ILocatorModelLookupService.class).lkupPeerModelById(id); + if (peerNode != null) { + // Remove from the model + fModel.getService(ILocatorModelUpdateService.class).remove(peerNode); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.tcf.services.ILocator.LocatorListener#peerHeartBeat(java.lang.String) + */ + public void peerHeartBeat(String id) { + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/listener/ModelAdapter.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/listener/ModelAdapter.java new file mode 100644 index 000000000..e68c020df --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/listener/ModelAdapter.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.listener; + +import org.eclipse.tm.te.tcf.locator.interfaces.IModelListener; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; + +/** + * Default model listener implementation. + */ +public class ModelAdapter implements IModelListener { + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.IModelListener#locatorModelChanged(org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel) + */ + public void locatorModelChanged(ILocatorModel model) { + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.IModelListener#locatorModelDisposed(org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel) + */ + public void locatorModelDisposed(ILocatorModel model) { + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.IModelListener#peerModelChanged(org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel, org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel) + */ + public void peerModelChanged(ILocatorModel model, IPeerModel peer) { + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/nodes/LocatorModel.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/nodes/LocatorModel.java new file mode 100644 index 000000000..6b2965ece --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/nodes/LocatorModel.java @@ -0,0 +1,333 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.nodes; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.ILocator; +import org.eclipse.tm.te.tcf.core.Tcf; +import org.eclipse.tm.te.tcf.core.interfaces.listeners.IChannelStateChangeListener; +import org.eclipse.tm.te.tcf.locator.Scanner; +import org.eclipse.tm.te.tcf.locator.activator.CoreBundleActivator; +import org.eclipse.tm.te.tcf.locator.interfaces.IModelListener; +import org.eclipse.tm.te.tcf.locator.interfaces.IScanner; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.preferences.IPreferenceKeys; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelLookupService; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelRefreshService; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelService; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelUpdateService; +import org.eclipse.tm.te.tcf.locator.listener.ChannelStateChangeListener; +import org.eclipse.tm.te.tcf.locator.listener.LocatorListener; +import org.eclipse.tm.te.tcf.locator.services.LocatorModelLookupService; +import org.eclipse.tm.te.tcf.locator.services.LocatorModelRefreshService; +import org.eclipse.tm.te.tcf.locator.services.LocatorModelUpdateService; +import org.eclipse.tm.te.tcf.locator.utils.IPAddressUtil; + + +/** + * Default locator model implementation. + */ +public class LocatorModel extends PlatformObject implements ILocatorModel { + // Flag to mark the model disposed + private boolean fDisposed; + + // The list of known peers + private final Map<String, IPeerModel> fPeers = new HashMap<String, IPeerModel>(); + + // Reference to the scanner + private IScanner fScanner = null; + + // Reference to the model locator listener + private ILocator.LocatorListener fLocatorListener = null; + // Reference to the model channel state change listener + private IChannelStateChangeListener fChannelStateChangeListener = null; + + // The list of registered model listeners + private final List<IModelListener> fModelListener = new ArrayList<IModelListener>(); + + // Reference to the refresh service + private final ILocatorModelRefreshService fRefreshService = new LocatorModelRefreshService(this); + // Reference to the lookup service + private final ILocatorModelLookupService fLookupService = new LocatorModelLookupService(this); + // Reference to the update service + private final ILocatorModelUpdateService fUpdateService = new LocatorModelUpdateService(this); + + /** + * Constructor. + */ + public LocatorModel() { + super(); + fDisposed = false; + + fChannelStateChangeListener = new ChannelStateChangeListener(this); + Tcf.addChannelStateChangeListener(fChannelStateChangeListener); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel#addListener(org.eclipse.tm.te.tcf.locator.core.interfaces.IModelListener) + */ + public void addListener(IModelListener listener) { + assert Protocol.isDispatchThread() && listener != null; + if (!fModelListener.contains(listener)) fModelListener.add(listener); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel#removeListener(org.eclipse.tm.te.tcf.locator.core.interfaces.IModelListener) + */ + public void removeListener(IModelListener listener) { + assert Protocol.isDispatchThread() && listener != null; + fModelListener.remove(listener); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel#getListener() + */ + public IModelListener[] getListener() { + return fModelListener.toArray(new IModelListener[fModelListener.size()]); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel#dispose() + */ + public void dispose() { + assert Protocol.isDispatchThread(); + + // If already disposed, we are done immediately + if (fDisposed) return; + + fDisposed = true; + + final IModelListener[] listeners = getListener(); + if (listeners.length > 0) { + Protocol.invokeLater(new Runnable() { + public void run() { + for (IModelListener listener : listeners) { + listener.locatorModelDisposed(LocatorModel.this); + } + } + }); + } + fModelListener.clear(); + + if (fLocatorListener != null) { + Protocol.getLocator().removeListener(fLocatorListener); + fLocatorListener = null; + } + + if (fChannelStateChangeListener != null) { + Tcf.removeChannelStateChangeListener(fChannelStateChangeListener); + fChannelStateChangeListener = null; + } + + if (fScanner != null) { + stopScanner(); + fScanner = null; + } + + fPeers.clear(); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel#isDisposed() + */ + public boolean isDisposed() { + return fDisposed; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel#getPeers() + */ + public IPeerModel[] getPeers() { + return fPeers.values().toArray(new IPeerModel[fPeers.values().size()]); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class) + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public Object getAdapter(Class adapter) { + if (adapter.isAssignableFrom(ILocator.LocatorListener.class)) { + return fLocatorListener; + } + if (adapter.isAssignableFrom(IScanner.class)) { + return fScanner; + } + if (adapter.isAssignableFrom(ILocatorModelRefreshService.class)) { + return fRefreshService; + } + if (adapter.isAssignableFrom(ILocatorModelLookupService.class)) { + return fLookupService; + } + if (adapter.isAssignableFrom(ILocatorModelUpdateService.class)) { + return fUpdateService; + } + if (adapter.isAssignableFrom(Map.class)) { + return fPeers; + } + + return super.getAdapter(adapter); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel#getService(java.lang.Class) + */ + @SuppressWarnings("unchecked") + public <V extends ILocatorModelService> V getService(Class<V> serviceInterface) { + assert serviceInterface != null; + 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 Protocol.isDispatchThread(); + assert Protocol.getLocator() != null; + + if (fLocatorListener == null) { + fLocatorListener = doCreateLocatorListener(this); + Protocol.getLocator().addListener(fLocatorListener); + } + } + + /** + * Creates the locator listener instance. + * + * @param model The parent model. Must be not <code>null</code>. + * @return The locator listener instance. + */ + protected ILocator.LocatorListener doCreateLocatorListener(ILocatorModel model) { + assert model != null; + return new LocatorListener(model); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel#getScanner() + */ + public IScanner getScanner() { + if (fScanner == null) fScanner = new Scanner(this); + return fScanner; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel#startScanner(long, long) + */ + public void startScanner(long delay, long schedule) { + 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.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel#stopScanner() + */ + public void stopScanner() { + if (fScanner != null) { + // Terminate the scanner + fScanner.terminate(); + // Reset the scanner reference + fScanner = null; + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel#validatePeerNodeForAdd(org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel) + */ + public IPeerModel validatePeerNodeForAdd(IPeerModel node) { + assert Protocol.isDispatchThread() && node != null; + + // Get the peer from the peer node + IPeer peer = node.getPeer(); + + 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 previousNode = agentId != null ? getService(ILocatorModelLookupService.class).lkupPeerModelByAgentId(agentId) : null; + if (previousNode != null) { + // 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(); + + boolean fireListener = false; + + String peerIP = peer.getAttributes().get(IPeer.ATTR_IP_HOST); + String previousPeerIP = previousPeer.getAttributes().get(IPeer.ATTR_IP_HOST); + if (canonical != null && canonical.equals(peerIP) && !canonical.equals(previousPeerIP)) { + // Remove the old node and replace it with the new new + fPeers.remove(previousNode.getPeer().getID()); + fireListener = true; + } else if (loopback != null && loopback.equals(peerIP) && !loopback.equals(previousPeerIP) + && (canonical == null || canonical != null && !canonical.equals(previousPeerIP))) { + // Remove the old node and replace it with the new new + fPeers.remove(previousNode.getPeer().getID()); + fireListener = true; + } else { + // Drop the current node + result = null; + } + + if (fireListener) { + final IModelListener[] listeners = getListener(); + if (listeners.length > 0) { + Protocol.invokeLater(new Runnable() { + public void run() { + for (IModelListener listener : listeners) { + listener.locatorModelChanged(LocatorModel.this); + } + } + }); + } + } + } + } + } + + return result; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/nodes/PeerModel.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/nodes/PeerModel.java new file mode 100644 index 000000000..50ac619b1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/nodes/PeerModel.java @@ -0,0 +1,398 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.nodes; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.locator.interfaces.IModelListener; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModelProperties; + + +/** + * Default peer model implementation. + */ +public class PeerModel extends PlatformObject implements IPeerModel { + // Reference to the parent locator model + private final ILocatorModel fParentModel; + + /** + * The custom properties map. The keys are always strings, the value might be any object. + */ + private Map<String, Object> fProperties = new LinkedHashMap<String, Object>(); + + /** + * Constructor. + * + * @param parent The parent locator model. Must be not <code>null</code>. + */ + public PeerModel(ILocatorModel parent) { + this(parent, null); + } + + /** + * Constructor. + * + * @param parent The parent locator model. Must be not <code>null</code>. + * @param peer The peer or <code>null</code>. + */ + public PeerModel(ILocatorModel parent, IPeer peer) { + super(); + + assert parent != null; + fParentModel = parent; + + setProperty(IPeerModelProperties.PROP_INSTANCE, peer); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#getModel() + */ + public ILocatorModel getModel() { + return (ILocatorModel)getAdapter(ILocatorModel.class); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#getPeer() + */ + public IPeer getPeer() { + return (IPeer)getAdapter(IPeer.class); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class) + */ + @SuppressWarnings({ "rawtypes" }) + @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 the only one which is allowed to call from any thread. + final Object[] object = new Object[1]; + if (Protocol.isDispatchThread()) { + object[0] = doGetAdapter(adapter); + } else { + Protocol.invokeAndWait(new Runnable() { + 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 Protocol.isDispatchThread(); + + if (adapter.isAssignableFrom(ILocatorModel.class)) { + return fParentModel; + } + + Object peer = getProperty(IPeerModelProperties.PROP_INSTANCE); + if (peer != null && adapter.isAssignableFrom(peer.getClass())) { + return peer; + } + + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#getProperties() + */ + public Map<String, Object> getProperties() { + assert Protocol.isDispatchThread(); + return Collections.unmodifiableMap(new HashMap<String, Object>(fProperties)); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#getProperty(java.lang.String) + */ + public Object getProperty(String key) { + assert Protocol.isDispatchThread(); + + if (!fProperties.containsKey(key) + && getPeer() != null && getPeer().getAttributes().containsKey(key)) { + return getPeer().getAttributes().get(key); + } + + return fProperties.get(key); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#getBooleanProperty(java.lang.String) + */ + public final boolean getBooleanProperty(String key) { + Object value = getProperty(key); + if (value instanceof Boolean) { + return ((Boolean)value).booleanValue(); + } + if (value instanceof String) { + String val = ((String)value).trim(); + return "TRUE".equalsIgnoreCase(val) || "1".equals(val) || "Y".equalsIgnoreCase(val) || //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + "JA".equalsIgnoreCase(val) || "YES".equalsIgnoreCase(val); //$NON-NLS-1$ //$NON-NLS-2$ + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#getLongProperty(java.lang.String) + */ + public final long getLongProperty(String key) { + Object value = getProperty(key); + if (value instanceof Long) { + return ((Long)value).longValue(); + } + else if (value instanceof Integer) { + return ((Integer)value).intValue(); + } + else if (value != null) { + try { + return Long.decode(value.toString()).longValue(); + } + catch (Exception e) {} + } + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#getIntProperty(java.lang.String) + */ + public final int getIntProperty(String key) { + Object value = getProperty(key); + try { + return value instanceof Integer ? ((Integer)value).intValue() : + (value != null ? Integer.decode(value.toString()).intValue() : -1); + } + catch (Exception e) { + return -1; + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#getStringProperty(java.lang.String) + */ + public final String getStringProperty(String key) { + Object value = getProperty(key); + return value instanceof String ? (String)value : + (value != null ? value.toString() : null); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#getFloatProperty(java.lang.String) + */ + public final float getFloatProperty(String key) { + Object value = getProperty(key); + try { + return value instanceof Float ? ((Float)value).floatValue() : + (value != null ? Float.parseFloat(value.toString()) : Float.NaN); + } + catch (Exception e) { + return Float.NaN; + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#getDoubleProperty(java.lang.String) + */ + public final double getDoubleProperty(String key) { + Object value = getProperty(key); + try { + return value instanceof Double ? ((Double)value).doubleValue() : + (value != null ? Double.parseDouble(value.toString()) : Double.NaN); + } + catch (Exception e) { + return Double.NaN; + } + + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#setProperties(java.util.Map) + */ + public final void setProperties(Map<String, Object> properties) { + assert Protocol.isDispatchThread() && properties != null; + + fProperties.clear(); + fProperties.putAll(properties); + + final IModelListener[] listeners = fParentModel.getListener(); + if (listeners.length > 0) { + Protocol.invokeLater(new Runnable() { + @SuppressWarnings("synthetic-access") + public void run() { + for (IModelListener listener : listeners) { + listener.peerModelChanged(fParentModel, PeerModel.this); + } + } + }); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#setProperty(java.lang.String, boolean) + */ + public final boolean setProperty(String key, boolean value) { + boolean oldValue = getBooleanProperty(key); + if (oldValue != value) { + return setProperty(key, Boolean.valueOf(value)); + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#setProperty(java.lang.String, long) + */ + public final boolean setProperty(String key, long value) { + long oldValue = getLongProperty(key); + if (oldValue != value) { + return setProperty(key, Long.valueOf(value)); + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#setProperty(java.lang.String, int) + */ + public final boolean setProperty(String key, int value) { + int oldValue = getIntProperty(key); + if (oldValue != value) { + return setProperty(key, Integer.valueOf(value)); + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#setProperty(java.lang.String, float) + */ + public final boolean setProperty(String key, float value) { + float oldValue = getFloatProperty(key); + if (oldValue != value) { + return setProperty(key, Float.valueOf(value)); + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#setProperty(java.lang.String, double) + */ + public final boolean setProperty(String key, double value) { + double oldValue = getDoubleProperty(key); + if (oldValue != value) { + return setProperty(key, Double.valueOf(value)); + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#setProperty(java.lang.String, java.lang.Object) + */ + public boolean setProperty(String key, Object value) { + assert Protocol.isDispatchThread(); + + Object oldValue = fProperties.get(key); + if ((oldValue == null && value != null) || (oldValue != null && !oldValue.equals(value))) { + if (value != null) { + fProperties.put(key, value); + } else { + fProperties.remove(key); + } + + final IModelListener[] listeners = fParentModel.getListener(); + if (listeners.length > 0) { + Protocol.invokeLater(new Runnable() { + @SuppressWarnings("synthetic-access") + public void run() { + for (IModelListener listener : listeners) { + listener.peerModelChanged(fParentModel, PeerModel.this); + } + } + }); + } + + return true; + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#clearProperties() + */ + public final void clearProperties() { + assert Protocol.isDispatchThread(); + fProperties.clear(); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#isProperty(java.lang.String, long) + */ + public final boolean isProperty(String key, long value) { + return getLongProperty(key) == value; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#isProperty(java.lang.String, boolean) + */ + public final boolean isProperty(String key, boolean value) { + return getBooleanProperty(key) == value; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#isProperty(java.lang.String, int) + */ + public final boolean isProperty(String key, int value) { + return getIntProperty(key) == value; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#isProperty(java.lang.String, float) + */ + public final boolean isProperty(String key, float value) { + return getFloatProperty(key) == value; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#isProperty(java.lang.String, double) + */ + public final boolean isProperty(String key, double value) { + return getDoubleProperty(key) == value; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#isPropertyIgnoreCase(java.lang.String, java.lang.String) + */ + public final boolean isPropertyIgnoreCase(String key, String value) { + String property = getStringProperty(key); + return (property == null && value == null) || (property != null && property.equalsIgnoreCase(value)); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel#isProperty(java.lang.String, java.lang.Object) + */ + public final boolean isProperty(String key, Object value) { + Object property = getProperty(key); + return (property == null && value == null) || (property != null && property.equals(value)); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/AbstractLocatorModelService.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/AbstractLocatorModelService.java new file mode 100644 index 000000000..34d36b732 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/AbstractLocatorModelService.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.services; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.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 fLocatorModel; + + /** + * Constructor. + * + * @param parentModel The parent locator model instance. Must be not <code>null</code>. + */ + public AbstractLocatorModelService(ILocatorModel parentModel) { + assert parentModel != null; + fLocatorModel = parentModel; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelService#getLocatorModel() + */ + public final ILocatorModel getLocatorModel() { + return fLocatorModel; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/LocatorModelLookupService.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/LocatorModelLookupService.java new file mode 100644 index 000000000..c744fe1bf --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/LocatorModelLookupService.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.services; + +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.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 be not <code>null</code>. + */ + public LocatorModelLookupService(ILocatorModel parentModel) { + super(parentModel); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.services.ILocatorModelLookupService#lkupPeerModelById(java.lang.String) + */ + public IPeerModel lkupPeerModelById(String id) { + assert Protocol.isDispatchThread() && id != null; + + 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.tm.te.tcf.locator.core.interfaces.services.ILocatorModelLookupService#lkupPeerModelByAgentId(java.lang.String) + */ + public IPeerModel lkupPeerModelByAgentId(String agentId) { + assert Protocol.isDispatchThread() && agentId != null; + + IPeerModel node = null; + for (IPeerModel candidate : getLocatorModel().getPeers()) { + IPeer peer = candidate.getPeer(); + if (agentId.equals(peer.getAgentID())) { + node = candidate; + break; + } + } + + return node; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/LocatorModelRefreshService.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/LocatorModelRefreshService.java new file mode 100644 index 000000000..dd2455d22 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/LocatorModelRefreshService.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.services; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.ILocator; +import org.eclipse.tm.te.tcf.core.Tcf; +import org.eclipse.tm.te.tcf.locator.ScannerRunnable; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelLookupService; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelRefreshService; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelUpdateService; +import org.eclipse.tm.te.tcf.locator.nodes.LocatorModel; +import org.eclipse.tm.te.tcf.locator.nodes.PeerModel; + + +/** + * Default locator model refresh service implementation. + */ +public class LocatorModelRefreshService extends AbstractLocatorModelService implements ILocatorModelRefreshService { + + /** + * Constructor. + * + * @param parentModel The parent locator model instance. Must be not <code>null</code>. + */ + public LocatorModelRefreshService(ILocatorModel parentModel) { + super(parentModel); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.services.ILocatorModelRefreshService#refresh() + */ + public void refresh() { + assert 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(); + 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 + if (peerNode != null) 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); + } + } + } + + // If there are remaining old children, remove them from the model (non-recursive) + for (IPeerModel oldChild : oldChildren) model.getService(ILocatorModelUpdateService.class).remove(oldChild); + + // Create and fire the notification event if non null +// if (dirty) { +// IWRNotificationEvent event = model.getFactory().newPropertyChangeEvent(model, IContainerModelNode.PROPERTY_CHANGED, null, null); +// if (event != null) WRNotificationManager.getInstance().fireEvent(event); +// } + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/LocatorModelUpdateService.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/LocatorModelUpdateService.java new file mode 100644 index 000000000..0ad455429 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/services/LocatorModelUpdateService.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.locator.services; + +import java.util.Collection; +import java.util.Map; + +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.locator.interfaces.IModelListener; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModelProperties; +import org.eclipse.tm.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 be not <code>null</code>. + */ + public LocatorModelUpdateService(ILocatorModel parentModel) { + super(parentModel); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.services.ILocatorModelUpdateService#add(org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel) + */ + public void add(IPeerModel peer) { + assert Protocol.isDispatchThread() && peer != null; + + @SuppressWarnings("unchecked") + Map<String, IPeerModel> peers = (Map<String, IPeerModel>)getLocatorModel().getAdapter(Map.class); + assert peers != null; + peers.put(peer.getPeer().getID(), peer); + + final IModelListener[] listeners = getLocatorModel().getListener(); + if (listeners.length > 0) { + Protocol.invokeLater(new Runnable() { + public void run() { + for (IModelListener listener : listeners) { + listener.locatorModelChanged(getLocatorModel()); + } + } + }); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.services.ILocatorModelUpdateService#remove(org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel) + */ + public void remove(IPeerModel peer) { + assert Protocol.isDispatchThread() && peer != null; + + @SuppressWarnings("unchecked") + Map<String, IPeerModel> peers = (Map<String, IPeerModel>)getLocatorModel().getAdapter(Map.class); + assert peers != null; + peers.remove(peer.getPeer().getID()); + + final IModelListener[] listeners = getLocatorModel().getListener(); + if (listeners.length > 0) { + Protocol.invokeLater(new Runnable() { + public void run() { + for (IModelListener listener : listeners) { + listener.locatorModelChanged(getLocatorModel()); + } + } + }); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.interfaces.services.ILocatorModelUpdateService#updatePeerServices(org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel, java.util.Collection, java.util.Collection) + */ + public void updatePeerServices(IPeerModel peerNode, Collection<String> localServices, Collection<String> remoteServices) { + assert Protocol.isDispatchThread() && peerNode != null; + + 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 be not <code>null</code>. + * @return The plain string. + */ + protected String makeString(Collection<String> collection) { + assert collection != null; + + 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.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/utils/IPAddressUtil.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/te/tcf/locator/utils/IPAddressUtil.java new file mode 100644 index 000000000..53bfcb748 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.locator/src/org/eclipse/tm/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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.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; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/.classpath b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/.classpath new file mode 100644 index 000000000..64c5e31b7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/.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/J2SE-1.5"/> + <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.tm.te.tcf.ui/.project b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/.project new file mode 100644 index 000000000..0a613f685 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.tm.te.tcf.ui</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/.settings/org.eclipse.jdt.core.prefs b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..39179c161 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,77 @@ +#Mon Nov 29 11:56:48 CET 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +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=error +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.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=ignore +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=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +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.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.5 diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/META-INF/MANIFEST.MF new file mode 100644 index 000000000..04b46de06 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/META-INF/MANIFEST.MF @@ -0,0 +1,20 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.tm.te.tcf.ui;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.tm.te.tcf.ui.activator.UIPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0", + org.eclipse.ui;bundle-version="3.6.2", + org.eclipse.ui.forms;bundle-version="3.5.2", + org.eclipse.ui.navigator;bundle-version="3.5.0", + org.eclipse.tm.tcf.core;bundle-version="0.3.0", + org.eclipse.tm.te.ui;bundle-version="1.0.0", + org.eclipse.tm.te.ui.views;bundle-version="1.0.0", + org.eclipse.tm.te.tcf.core;bundle-version="1.0.0", + org.eclipse.tm.te.tcf.locator;bundle-version="1.0.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.tm.te.tcf.ui.tables;version="1.0.0" diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/build.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/build.properties new file mode 100644 index 000000000..d24082bdb --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.properties,\ + plugin.xml,\ + icons/ diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/dtool16/newconnection_wiz.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/dtool16/newconnection_wiz.gif Binary files differnew file mode 100644 index 000000000..5d9eae9e5 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/dtool16/newconnection_wiz.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/etool16/newconnection_wiz.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/etool16/newconnection_wiz.gif Binary files differnew file mode 100644 index 000000000..9f2b4acc7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/etool16/newconnection_wiz.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/obj16/rootNode_obj.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/obj16/rootNode_obj.gif Binary files differnew file mode 100644 index 000000000..f1bf387e1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/obj16/rootNode_obj.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/obj16/target.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/obj16/target.gif Binary files differnew file mode 100644 index 000000000..e9df7b871 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/obj16/target.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/gold_ovr.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/gold_ovr.gif Binary files differnew file mode 100644 index 000000000..a05073c2f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/gold_ovr.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/green_ovr.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/green_ovr.gif Binary files differnew file mode 100644 index 000000000..35ed218ad --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/green_ovr.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/grey_ovr.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/grey_ovr.gif Binary files differnew file mode 100644 index 000000000..3f5fb9f6f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/grey_ovr.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/redX_ovr.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/redX_ovr.gif Binary files differnew file mode 100644 index 000000000..8fa687bb2 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/redX_ovr.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/red_ovr.gif b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/red_ovr.gif Binary files differnew file mode 100644 index 000000000..ea5aaa545 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/icons/ovr16/red_ovr.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/plugin.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/plugin.properties new file mode 100644 index 000000000..910ffda8c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/plugin.properties @@ -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: +# Uwe Stieber (Wind River) - initial API and implementation +################################################################################## + +pluginName = Target Explorer, TCF UI Plug-in +providerName = Eclipse.org + +# ***** Editor Pages ***** + +NodePropertiesEditorPage.name=General + +# ***** Command Contributions ***** +TcfDataSource.command.category.name=Target Explorer Commands (TCF) + +TcfDataSource.command.refresh.name=Refresh Command +TcfDataSource.command.refresh.label=Re&fresh +TcfDataSource.command.refresh.tooltip=Refresh + +TcfDataSource.command.addPeer.name=Add New Peer Command +TcfDataSource.command.addPeer.label=&New Peer... +TcfDataSource.command.addPeer.tooltip=Adds a new peer to the discovery view. diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/plugin.xml b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/plugin.xml new file mode 100644 index 000000000..aee18917d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/plugin.xml @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> + +<!-- Common navigator contributions --> + <extension point="org.eclipse.ui.navigator.viewer"> + <viewerContentBinding viewerId="org.eclipse.tm.te.ui.views.TargetExplorer"> + <includes> + <contentExtension + isRoot="true" + pattern="org.eclipse.tm.te.datasource.tcf"/> + </includes> + </viewerContentBinding> + </extension> + + <extension point="org.eclipse.ui.navigator.navigatorContent"> + <navigatorContent + activeByDefault="true" + contentProvider="org.eclipse.tm.te.tcf.ui.internal.navigator.ContentProviderDelegate" + icon="icons/obj16/rootNode_obj.gif" + id="org.eclipse.tm.te.datasource.tcf" + labelProvider="org.eclipse.tm.te.tcf.ui.internal.navigator.LabelProvider" + name="Dynamic Target Discovery (TCF)" + priority="normal"> + <triggerPoints> + <instanceof value="org.eclipse.tm.te.ui.views.interfaces.IRoot"/> + <instanceof value="org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel"/> + <instanceof value="org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel"/> + </triggerPoints> + <commonSorter + class="org.eclipse.tm.te.tcf.ui.internal.navigator.Sorter" + id="org.eclipse.tm.te.tcf.ui.navigator.sorter"/> + </navigatorContent> + </extension> + +<!-- Target Explorer Details Editor page contributions --> + <extension point="org.eclipse.tm.te.ui.views.editorPages"> + <editorPage + class="org.eclipse.tm.te.tcf.ui.internal.editor.pages.NodePropertiesEditorPage" + name="%NodePropertiesEditorPage.name" + id="org.eclipse.tm.te.tcf.ui.NodePropertiesEditorPage"> + </editorPage> + </extension> + +<!-- Target Explorer Details Editor page binding contributions --> + <extension point="org.eclipse.tm.te.ui.views.editorPageBindings"> + <editorPageBinding + id="org.eclipse.tm.te.tcf.ui.binding.NodePropertiesEditorPage" + pageId="org.eclipse.tm.te.tcf.ui.NodePropertiesEditorPage" + insertBefore="first"> + <enablement> + <with variable="activeEditorInput"> + <instanceof value="org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel"/> + </with> + </enablement> + </editorPageBinding> + </extension> + +<!-- Target Explorer menu contributions --> + <extension point="org.eclipse.ui.menus"> + <menuContribution locationURI="popup:org.eclipse.tm.te.ui.views.TargetExplorer#Popup?after=group.new"> + <command + commandId="org.eclipse.tm.te.tcf.ui.command.addPeer" + disabledIcon="icons/dtool16/newconnection_wiz.gif" + helpContextId="org.eclipse.tm.te.tcf.ui.command_AddPeer" + icon="icons/etool16/newconnection_wiz.gif" + id="org.eclipse.tm.te.tcf.ui.commands.addPeer" + label="%TcfDataSource.command.addPeer.label" + style="push" + tooltip="%TcfDataSource.command.addPeer.tooltip"> + <visibleWhen checkEnabled="false"> + <with variable="selection"> + <count value="1"/> + <iterate operator="and" ifEmpty="false"> + <instanceof value="org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel"/> + </iterate> + </with> + </visibleWhen> + </command> + </menuContribution> + + <menuContribution locationURI="popup:org.eclipse.tm.te.ui.views.TargetExplorer#Popup?after=group.refresh"> + <command + commandId="org.eclipse.tm.te.tcf.ui.command.refresh" + disabledIcon="platform:/plugin/org.eclipse.ui.ide/icons/full/dlcl16/refresh_nav.gif" + helpContextId="org.eclipse.tm.te.tcf.ui.command_Refresh" + icon="platform:/plugin/org.eclipse.ui.ide/icons/full/elcl16/refresh_nav.gif" + id="org.eclipse.tm.te.tcf.ui.commands.refresh" + label="%TcfDataSource.command.refresh.label" + style="push" + tooltip="%TcfDataSource.command.refresh.tooltip"> + <visibleWhen checkEnabled="false"> + <with variable="selection"> + <count value="1"/> + <iterate operator="and" ifEmpty="false"> + <instanceof value="org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel"/> + </iterate> + </with> + </visibleWhen> + </command> + <separator name="operationsGroupMarker" visible="true"/> + </menuContribution> + </extension> + +<!-- TCF data source command contributions --> + <extension point="org.eclipse.ui.commands"> + <category + id="org.eclipse.tm.te.tcf.ui.commands.category" + name="%TcfDataSource.command.category.name"> + </category> + <command + categoryId="org.eclipse.tm.te.tcf.ui.commands.category" + helpContextId="org.eclipse.tm.te.tcf.ui.command_Refresh" + id="org.eclipse.tm.te.tcf.ui.command.refresh" + name="%TcfDataSource.command.refresh.name"> + </command> + <command + categoryId="org.eclipse.tm.te.tcf.ui.commands.category" + helpContextId="org.eclipse.tm.te.tcf.ui.command_AddPeer" + id="org.eclipse.tm.te.tcf.ui.command.addPeer" + name="%TcfDataSource.command.addPeer.name"> + </command> + </extension> + +<!-- TCF data source handler contributions --> + <extension point="org.eclipse.ui.handlers"> + <handler + class="org.eclipse.tm.te.tcf.ui.internal.handler.RefreshCommandHandler" + commandId="org.eclipse.tm.te.tcf.ui.command.refresh"> + </handler> + + <handler + class="org.eclipse.tm.te.tcf.ui.internal.handler.AddPeerCommandHandler" + commandId="org.eclipse.tm.te.tcf.ui.command.addPeer"> + </handler> + </extension> +</plugin> diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/activator/UIPlugin.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/activator/UIPlugin.java new file mode 100644 index 000000000..751715329 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/activator/UIPlugin.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.activator; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm.te.tcf.ui.internal.registries.InternalImageRegistry; +import org.eclipse.tm.te.ui.images.AbstractImageDescriptor; +import org.eclipse.tm.te.ui.images.AbstractImageRegistry; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + + +/** + * The activator class controls the plug-in life cycle + */ +public class UIPlugin extends AbstractUIPlugin { + // The shared instance + private static UIPlugin plugin; + + /** + * Constructor. + */ + public UIPlugin() { + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static UIPlugin 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; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#initializeImageRegistry(org.eclipse.jface.resource.ImageRegistry) + */ + @Override + protected void initializeImageRegistry(ImageRegistry registry) { + if (registry instanceof InternalImageRegistry) { + ((InternalImageRegistry)registry).initialize(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#createImageRegistry() + */ + @Override + protected ImageRegistry createImageRegistry() { + return new InternalImageRegistry(this); + } + + /** + * Loads the image registered under the specified key from the image + * registry and returns the <code>Image</code> object instance. + * + * @param key The key the image is registered with. + * @return The <code>Image</code> object instance or <code>null</code>. + */ + public static Image getImage(String key) { + return getDefault().getImageRegistry().get(key); + } + + /** + * Loads the image registered under the specified key from the image + * registry and returns the <code>ImageDescriptor</code> object instance. + * + * @param key The key the image is registered with. + * @return The <code>ImageDescriptor</code> object instance or <code>null</code>. + */ + public static ImageDescriptor getImageDescriptor(String key) { + return getDefault().getImageRegistry().getDescriptor(key); + } + + /** + * Loads the image given by the specified image descriptor from the image + * registry. If the image has been loaded ones before already, the cached + * <code>Image</code> object instance is returned. Otherwise, the <code> + * Image</code> object instance will be created and cached before returned. + * + * @param descriptor The image descriptor. + * @return The corresponding <code>Image</code> object instance or <code>null</code>. + */ + public static Image getSharedImage(AbstractImageDescriptor descriptor) { + return ((AbstractImageRegistry)getDefault().getImageRegistry()).getSharedImage(descriptor); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/dialogs/AddPeerDialog.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/dialogs/AddPeerDialog.java new file mode 100644 index 000000000..ab8446780 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/dialogs/AddPeerDialog.java @@ -0,0 +1,267 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.dialogs; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.te.tcf.ui.internal.help.IContextHelpIds; +import org.eclipse.tm.te.tcf.ui.internal.nls.Messages; +import org.eclipse.tm.te.ui.dialogs.CustomTrayDialog; + + +/** + * Target Explorer: Add peer dialog implementation. + */ +public class AddPeerDialog extends CustomTrayDialog { + private Combo fTransportTypeControl; + private Text fAddressControl; + private Text fPortControl; + private Text fPeerIdControl; + private Text fPeerNameControl; + + private Map<String, String> fPeerAttributes = null; + + /** + * Constructor. + * + * @param parent The parent shell used to view the dialog. + */ + public AddPeerDialog(Shell parent) { + this(parent, IContextHelpIds.ADD_PEER_DIALOG); + } + + /** + * Constructor. + * + * @param parent The parent shell used to view the dialog. + * @param contextHelpId The dialog context help id or <code>null</code>. + */ + public AddPeerDialog(Shell parent, String contextHelpId) { + super(parent, contextHelpId); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.ide.target.ui.dialogs.WRUnifiedTitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + + configureTitles(); + + Composite panel = new Composite(composite, SWT.NONE); + panel.setLayout(new GridLayout(2, false)); + panel.setLayoutData(new GridData(GridData.FILL_BOTH)); + + // Add the controls + Label label = new Label(panel, SWT.NONE); + label.setText(Messages.TransportTypeControl_label); + + fTransportTypeControl = new Combo(panel, SWT.READ_ONLY); + fTransportTypeControl.setItems(new String[] { "TCP" }); //$NON-NLS-1$ + fTransportTypeControl.select(0); + fTransportTypeControl.setEnabled(false); + fTransportTypeControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + label = new Label(panel, SWT.NONE); + label.setText(Messages.AgentHostControl_label); + + fAddressControl = new Text(panel, SWT.SINGLE | SWT.BORDER); + fAddressControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + fAddressControl.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updatePeerId(); + } + }); + + label = new Label(panel, SWT.NONE); + label.setText(Messages.AgentPortControl_label); + + fPortControl = new Text(panel, SWT.SINGLE | SWT.BORDER); + fPortControl.setText("1534"); //$NON-NLS-1$ + fPortControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + fPortControl.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updatePeerId(); + } + }); + + label = new Label(panel, SWT.NONE); + label.setText(Messages.PeerIdControl_label); + + fPeerIdControl = new Text(panel, SWT.SINGLE | SWT.BORDER); + fPeerIdControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + label = new Label(panel, SWT.NONE); + label.setText(Messages.PeerNameControl_label); + + fPeerNameControl = new Text(panel, SWT.SINGLE | SWT.BORDER); + fPeerNameControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // Setup the control content + setupContent(); + + // Adjust the font + applyDialogFont(composite); + + return composite; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createButtonBar(Composite parent) { + Control control = super.createButtonBar(parent); + validateDialog(); + return control; + } + + /** + * Configure the dialog title and the title area content. The method + * is called from {@link #createDialogArea(Composite)}. + */ + protected void configureTitles() { + setDialogTitle(Messages.AddPeerDialog_title); + } + + /** + * Setup the control content. + */ + protected void setupContent() { + restoreWidgetValues(); + updatePeerId(); + } + + /** + * Update peer id control. + */ + protected void updatePeerId() { + String address = fAddressControl.getText(); + String port = fPortControl.getText(); + String type = fTransportTypeControl.getText(); + + if (!"".equals(address) && !"".equals(port)) { //$NON-NLS-1$ //$NON-NLS-2$ + fPeerIdControl.setText(type + ":" //$NON-NLS-1$ + + address + ":" //$NON-NLS-1$ + + port); + } else { + fPeerIdControl.setText(""); //$NON-NLS-1$ + } + + validateDialog(); + } + + /** + * Validates the dialog. + */ + protected void validateDialog() { + boolean valid = true; + + if ("".equals(fAddressControl.getText()) || "".equals(fPortControl)) { //$NON-NLS-1$ //$NON-NLS-2$ + valid = false; + } + + if (getButton(IDialogConstants.OK_ID) != null) + getButton(IDialogConstants.OK_ID).setEnabled(valid); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#cancelPressed() + */ + @Override + protected void cancelPressed() { + // Dispose the peer attributes + fPeerAttributes = null; + + super.cancelPressed(); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.ide.target.ui.dialogs.WRUnifiedTitleAreaDialog#okPressed() + */ + @Override + protected void okPressed() { + saveWidgetValues(); + + // Create a new peer attributes map + fPeerAttributes = new HashMap<String, String>(); + // Update with the current control content + updatePeerAttributes(fPeerAttributes); + + super.okPressed(); + } + + /** + * Updates the given attributes map with the current control content. + */ + protected void updatePeerAttributes(Map<String, String> peerAttributes) { + assert peerAttributes != null; + + peerAttributes.put(IPeer.ATTR_IP_HOST, fAddressControl.getText()); + peerAttributes.put(IPeer.ATTR_IP_PORT, fPortControl.getText()); + peerAttributes.put(IPeer.ATTR_ID, fPeerIdControl.getText()); + peerAttributes.put(IPeer.ATTR_NAME, fPeerNameControl.getText()); + peerAttributes.put(IPeer.ATTR_TRANSPORT_NAME, fTransportTypeControl.getText()); + } + + /** + * Returns the peer attributes. + * + * @return The peer attributes or <code>null</code> if canceled. + */ + public final Map<String, String> getPeerAttributes() { + return fPeerAttributes; + } + + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.ide.target.ui.dialogs.WRUnifiedTitleAreaDialog#saveWidgetValues() + */ + protected void saveWidgetValues() { + IDialogSettings settings = getDialogSettings(); + if (settings != null) { + // The transport type control is not saved + settings.put(IPeer.ATTR_IP_HOST, fAddressControl.getText()); + settings.put(IPeer.ATTR_IP_PORT, fPortControl.getText()); + settings.put(IPeer.ATTR_ID, fPeerIdControl.getText()); + settings.put(IPeer.ATTR_NAME, fPeerNameControl.getText()); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.ide.target.ui.dialogs.WRUnifiedTitleAreaDialog#restoreWidgetValues() + */ + protected void restoreWidgetValues() { + IDialogSettings settings = getDialogSettings(); + if (settings != null) { + // The transport type control is not restored + if (settings.get(IPeer.ATTR_IP_HOST) != null) fAddressControl.setText(settings.get(IPeer.ATTR_IP_HOST)); + if (settings.get(IPeer.ATTR_IP_PORT) != null) fPortControl.setText(settings.get(IPeer.ATTR_IP_PORT)); + if (settings.get(IPeer.ATTR_ID) != null) fPeerIdControl.setText(settings.get(IPeer.ATTR_ID)); + if (settings.get(IPeer.ATTR_NAME) != null) fPeerNameControl.setText(settings.get(IPeer.ATTR_NAME)); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/editor/pages/NodePropertiesEditorPage.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/editor/pages/NodePropertiesEditorPage.java new file mode 100644 index 000000000..3dac76862 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/editor/pages/NodePropertiesEditorPage.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.editor.pages; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tm.te.tcf.ui.internal.help.IContextHelpIds; +import org.eclipse.tm.te.tcf.ui.tables.NodePropertiesContentProvider; +import org.eclipse.tm.te.tcf.ui.tables.NodePropertiesLabelProvider; +import org.eclipse.tm.te.tcf.ui.tables.NodePropertiesViewerComparator; +import org.eclipse.tm.te.ui.forms.CustomFormToolkit; +import org.eclipse.tm.te.ui.nls.Messages; +import org.eclipse.tm.te.ui.tables.properties.NodePropertiesTableControl; +import org.eclipse.tm.te.ui.views.editor.AbstractEditorPage; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.widgets.ExpandableComposite; +import org.eclipse.ui.forms.widgets.Section; +import org.eclipse.ui.forms.widgets.TableWrapData; + + +/** + * Target Explorer: TCF node properties details editor page implementation. + */ +public class NodePropertiesEditorPage extends AbstractEditorPage { + // The references to the pages subcontrol's (needed for disposal) + private NodePropertiesTableControl fNodePropertiesTableControl; + + // Reference to the form toolkit instance + private CustomFormToolkit fToolkit = null; + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.editor.FormPage#dispose() + */ + @Override + public void dispose() { + if (fNodePropertiesTableControl != null) { fNodePropertiesTableControl.dispose(); fNodePropertiesTableControl = null; } + super.dispose(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.editor.FormPage#createFormContent(org.eclipse.ui.forms.IManagedForm) + */ + @Override + protected void createFormContent(IManagedForm managedForm) { + // Configure the managed form + configureManagedForm(managedForm); + + // Get the form body + Composite body = managedForm.getForm().getBody(); + + // Create the toolkit instance + fToolkit = new CustomFormToolkit(managedForm.getToolkit()); + + // Do create the content of the form now + doCreateFormContent(body, fToolkit); + + // Re-arrange the controls + managedForm.reflow(true); + } + + /** + * Configure the managed form to be ready for usage. + * + * @param managedForm The managed form. Must be not <code>null</code>. + */ + protected void configureManagedForm(IManagedForm managedForm) { + assert managedForm != null; + + // Configure main layout + Composite body = managedForm.getForm().getBody(); + GridLayout layout = new GridLayout(); + layout.marginHeight = 2; layout.marginWidth = 0; + body.setLayout(layout); + body.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); + + // Set context help id + PlatformUI.getWorkbench().getHelpSystem().setHelp(managedForm.getForm(), IContextHelpIds.NODE_PROPERTIES_EDITOR_PAGE); + } + + /** + * Do create the managed form content. + * + * @param parent The parent composite. Must be not <code>null</code> + * @param toolkit The {@link CustomFormToolkit} instance. Must be not <code>null</code>. + */ + protected void doCreateFormContent(Composite parent, CustomFormToolkit toolkit) { + assert parent != null && toolkit != null; + + Section section = toolkit.getFormToolkit().createSection(parent, ExpandableComposite.TITLE_BAR); + String title = NLS.bind(Messages.NodePropertiesTableControl_section_title, Messages.NodePropertiesTableControl_section_title_noSelection); + // Stretch to a length of 40 characters to make sure the title can be changed + // to hold and show text up to this length + while (title.length() < 40) { + title += " "; //$NON-NLS-1$ + } + // Set the title to the section + section.setText(title); + section.setLayoutData(new GridData(GridData.FILL_BOTH)); + + // Create the client area + Composite client = toolkit.getFormToolkit().createComposite(section); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; layout.marginHeight = 0; + client.setLayout(layout); + section.setClient(client); + + // Setup the node properties table control + fNodePropertiesTableControl = doCreateNodePropertiesTableControl(); + assert fNodePropertiesTableControl != null; + fNodePropertiesTableControl.setupFormPanel((Composite)section.getClient(), toolkit); + + // Set the initial input + fNodePropertiesTableControl.getViewer().setInput(getEditorInputNode()); + } + + /** + * Creates and returns a new node properties table control. + * + * @return The new node properties table control. + */ + protected NodePropertiesTableControl doCreateNodePropertiesTableControl() { + return new NodePropertiesTableControl(this) { + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.tables.NodePropertiesTableControl#doCreateTableViewerContentProvider(org.eclipse.jface.viewers.TableViewer) + */ + @Override + protected IStructuredContentProvider doCreateTableViewerContentProvider(TableViewer viewer) { + return new NodePropertiesContentProvider(true); + } + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.tables.properties.NodePropertiesTableControl#doCreateTableViewerLabelProvider(org.eclipse.jface.viewers.TableViewer) + */ + @Override + protected ITableLabelProvider doCreateTableViewerLabelProvider(TableViewer viewer) { + return new NodePropertiesLabelProvider(viewer); + } + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.tables.NodePropertiesTableControl#doCreateTableViewerComparator(org.eclipse.jface.viewers.TableViewer) + */ + @Override + protected ViewerComparator doCreateTableViewerComparator(TableViewer viewer) { + return new NodePropertiesViewerComparator(viewer, (ITableLabelProvider)viewer.getLabelProvider()); + } + }; + } + + /** + * Returns the associated node properties table control. + * + * @return The associated node properties table control or <code>null</code>. + */ + protected final NodePropertiesTableControl getNodePropertiesTableControl() { + return fNodePropertiesTableControl; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/handler/AddPeerCommandHandler.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/handler/AddPeerCommandHandler.java new file mode 100644 index 000000000..de0f820d9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/handler/AddPeerCommandHandler.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.handler; + +import java.util.Map; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.core.Tcf; +import org.eclipse.tm.te.tcf.core.interfaces.IChannelManager; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelLookupService; +import org.eclipse.tm.te.tcf.ui.internal.dialogs.AddPeerDialog; +import org.eclipse.tm.te.tcf.ui.internal.model.Model; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; + + +/** + * Target Explorer: Adds a new peer to the TCF locator model. + */ +public class AddPeerCommandHandler extends AbstractHandler { + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + public Object execute(ExecutionEvent event) throws ExecutionException { + // Get the shell + Shell shell = HandlerUtil.getActiveShell(event); + // Open the dialog + AddPeerDialog dialog = new AddPeerDialog(shell); + if (dialog.open() == Window.OK) { + // Get the new peer attributes + final Map<String, String> peerAttributes = dialog.getPeerAttributes(); + if (peerAttributes != null) { + // Try to connect to the peer + IChannel channel = null; + try { + IWorkbenchPart activePart = HandlerUtil.getActivePart(event); + IEditorPart editorPart = activePart != null ? (IEditorPart)activePart.getAdapter(IEditorPart.class) : null; + final ISelectionProvider selectionProvider = editorPart != null ? editorPart.getEditorSite().getSelectionProvider() : null; + + Tcf.getChannelManager().openChannel(peerAttributes, new IChannelManager.DoneOpenChannel() { + public void doneOpenChannel(Throwable error, IChannel channel) { + if (error == null) { + IPeer peer = channel.getRemotePeer(); + if (selectionProvider != null && peer != null) { + // OK, we have the peer instance now, for the rest, + // we need the locator model + ILocatorModel model = Model.getModel(); + if (model != null) { + final IPeerModel peerNode = model.getService(ILocatorModelLookupService.class).lkupPeerModelById(peer.getID()); + if (peerNode != null) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + selectionProvider.setSelection(new StructuredSelection(peerNode)); + } + }); + } + } + } + } + + channel.close(); + } + }); + } catch (Exception e) { + } finally { + // Close the channel again + if (channel != null) { + final IChannel finChannel = channel; + if (Protocol.isDispatchThread()) { + finChannel.close(); + } else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + finChannel.close(); + } + }); + } + } + } + } + } + + return null; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/handler/RefreshCommandHandler.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/handler/RefreshCommandHandler.java new file mode 100644 index 000000000..5c6e804a7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/handler/RefreshCommandHandler.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.handler; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelRefreshService; +import org.eclipse.ui.handlers.HandlerUtil; + + +/** + * Target Explorer: TCF refresh command handler. + */ +public class RefreshCommandHandler extends AbstractHandler { + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getCurrentSelection(event); + if (selection instanceof IStructuredSelection && !selection.isEmpty()) { + List<ILocatorModel> refreshedModels = new ArrayList<ILocatorModel>(); + Iterator<?> iterator = ((IStructuredSelection)selection).iterator(); + while (iterator.hasNext()) { + Object element = iterator.next(); + if (element instanceof IAdaptable) { + final ILocatorModel model = (ILocatorModel)((IAdaptable)element).getAdapter(ILocatorModel.class); + if (model != null && !refreshedModels.contains(model)) { + if (Protocol.isDispatchThread()) { + model.getService(ILocatorModelRefreshService.class).refresh(); + } else { + Protocol.invokeLater(new Runnable() { + public void run() { + model.getService(ILocatorModelRefreshService.class).refresh(); + } + }); + } + refreshedModels.add(model); + } + } + } + + } + + return null; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/help/IContextHelpIds.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/help/IContextHelpIds.java new file mode 100644 index 000000000..6497cb459 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/help/IContextHelpIds.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.help; + +import org.eclipse.tm.te.tcf.ui.activator.UIPlugin; + +/** + * Target Explorer: Context help id definitions. + */ +public interface IContextHelpIds { + + /** + * TCF data source UI plug-in common context help id prefix. + */ + public final static String PREFIX = UIPlugin.getUniqueIdentifier() + "."; //$NON-NLS-1$ + + /** + * Add new peer dialog. + */ + public final static String ADD_PEER_DIALOG = PREFIX + "AddPeerDialog"; //$NON-NLS-1$ + + /** + * Target Explorer details editor page: Node properties + */ + public final static String NODE_PROPERTIES_EDITOR_PAGE = PREFIX + "NodePropertiesEditorPage"; //$NON-NLS-1$ +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/model/Model.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/model/Model.java new file mode 100644 index 000000000..2171b623e --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/model/Model.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.model; + +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.nodes.LocatorModel; +import org.eclipse.tm.te.tcf.ui.internal.navigator.ModelListener; + + +/** + * Target Explorer: Helper class to instantiate and initialize the TCF locator model. + */ +public final class Model { + // Reference to the locator model + /* default */ static ILocatorModel fLocatorModel; + + /** + * Returns the locator model. If not yet initialized, + * initialize the locator model. + * + * @return The locator model. + */ + public static ILocatorModel getModel() { + // Access to the locator model must happen in the TCF dispatch thread + if (fLocatorModel == null) { + if (Protocol.isDispatchThread()) { + initialize(); + } else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + initialize(); + } + }); + } + } + return fLocatorModel; + } + + /** + * Initialize the root node. Must be called within the TCF dispatch thread. + */ + protected static void initialize() { + assert Protocol.isDispatchThread(); + + fLocatorModel = new LocatorModel(); + // Register the model listener + fLocatorModel.addListener(new ModelListener(fLocatorModel)); + // Start the scanner + fLocatorModel.startScanner(5000, 120000); + } + + /** + * Dispose the root node. + */ + public static void dispose() { + if (fLocatorModel == null) return; + + // Access to the locator model must happen in the TCF dispatch thread + if (Protocol.isDispatchThread()) { + fLocatorModel.dispose(); + } else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + fLocatorModel.dispose(); + } + }); + } + + fLocatorModel = null; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/ContentProviderDelegate.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/ContentProviderDelegate.java new file mode 100644 index 000000000..ac3e4d11e --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/ContentProviderDelegate.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.navigator; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.core.Tcf; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.services.ILocatorModelRefreshService; +import org.eclipse.tm.te.tcf.ui.internal.model.Model; +import org.eclipse.tm.te.ui.views.interfaces.IRoot; + + +/** + * Target Explorer: Content provider delegate implementation. + */ +public class ContentProviderDelegate implements ITreeContentProvider { + private final static Object[] NO_ELEMENTS = new Object[0]; + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) + */ + public Object[] getChildren(Object parentElement) { + Object[] children = NO_ELEMENTS; + + // If the parent element is null or IRoot, than we assume + // the locator model as parent element. + if (parentElement == null || parentElement instanceof IRoot) { + parentElement = Model.getModel(); + } + // If it is the locator model, get the peers + if (parentElement instanceof ILocatorModel) { + children = ((ILocatorModel)parentElement).getPeers(); + } + + return children; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) + */ + public Object getParent(Object element) { + // If it is a peer model node, return the parent locator model + if (element instanceof IPeerModel) { + return ((IPeerModel)element).getModel(); + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) + */ + public boolean hasChildren(Object element) { + boolean hasChildren = false; + + if (element instanceof ILocatorModel) { + hasChildren = ((ILocatorModel)element).getPeers().length > 0; + } + + return hasChildren; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + */ + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + Model.dispose(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + if (newInput instanceof IRoot) { + final ILocatorModel model = Model.getModel(); + // If the TCF framework is not running yet, run the refresh asynchronous + if (Tcf.isRunning() && Protocol.isDispatchThread()) { + model.getService(ILocatorModelRefreshService.class).refresh(); + } else { + Protocol.invokeLater(new Runnable() { + public void run() { + model.getService(ILocatorModelRefreshService.class).refresh(); + } + }); + } + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/LabelProvider.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/LabelProvider.java new file mode 100644 index 000000000..6dea9bcad --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/LabelProvider.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.navigator; + +import org.eclipse.jface.viewers.DecoratingLabelProvider; + +/** + * Target Explorer: Decorating label provider. + */ +public class LabelProvider extends DecoratingLabelProvider { + private final static LabelProviderDelegate DELEGATE = new LabelProviderDelegate(); + + /** + * Constructor. + */ + public LabelProvider() { + super(DELEGATE, DELEGATE); + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/LabelProviderDelegate.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/LabelProviderDelegate.java new file mode 100644 index 000000000..2632f87b4 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/LabelProviderDelegate.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.navigator; + +import org.eclipse.jface.viewers.ILabelDecorator; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.ui.activator.UIPlugin; +import org.eclipse.tm.te.tcf.ui.internal.navigator.images.PeerImageDescriptor; +import org.eclipse.tm.te.tcf.ui.internal.registries.InternalImageRegistry; +import org.eclipse.tm.te.ui.images.AbstractImageDescriptor; + + +/** + * Target Explorer: Label provider delegate implementation. + */ +public class LabelProviderDelegate extends LabelProvider implements ILabelDecorator { + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + */ + @Override + public String getText(Object element) { + if (element instanceof IPeerModel) { + String label = null; + + final IPeer peer = ((IPeerModel)element).getPeer(); + final String[] peerName = new String[1]; + if (Protocol.isDispatchThread()) { + peerName[0] = peer.getName(); + } else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + peerName[0] = peer.getName(); + } + }); + } + label = peerName[0]; + + if (label != null && !"".equals(label.trim())) { //$NON-NLS-1$ + return label; + } + } + + return ""; //$NON-NLS-1$ + } + + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object) + */ + @Override + public Image getImage(Object element) { + if (element instanceof IPeerModel) { + return UIPlugin.getImage(InternalImageRegistry.OBJ_Target); + } + + return super.getImage(element); + } + + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ILabelDecorator#decorateImage(org.eclipse.swt.graphics.Image, java.lang.Object) + */ + public Image decorateImage(Image image, Object element) { + Image decoratedImage = null; + + if (image != null && element instanceof IPeerModel) { + AbstractImageDescriptor descriptor = new PeerImageDescriptor(UIPlugin.getDefault().getImageRegistry(), + image, + (IPeerModel)element); + decoratedImage = UIPlugin.getSharedImage(descriptor); + } + + return decoratedImage; + } + + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ILabelDecorator#decorateText(java.lang.String, java.lang.Object) + */ + public String decorateText(String text, Object element) { + if (element instanceof IPeerModel) { + String label = text; + + final IPeer peer = ((IPeerModel)element).getPeer(); + final StringBuilder builder = new StringBuilder(label != null && !"".equals(label.trim()) ? label.trim() : "<noname>"); //$NON-NLS-1$ //$NON-NLS-2$ + if (Protocol.isDispatchThread()) { + doDecorateText(builder, peer); + } else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + doDecorateText(builder, peer); + } + }); + } + label = builder.toString(); + + if (label != null && !"".equals(label.trim()) && !"<noname>".equals(label.trim())) { //$NON-NLS-1$ //$NON-NLS-2$ + return label; + } + } + return null; + } + + /** + * Decorate the text with some peer attributes. + * <p> + * <b>Note:</b> Must be called with the TCF event dispatch thread. + * + * @param builder The string builder to decorate. Must be not <code>null</code>. + * @param peer The peer. Must be not <code>null</code>. + */ + /* default */ void doDecorateText(StringBuilder builder, IPeer peer) { + assert Protocol.isDispatchThread() && builder != null && peer != null; + + String osName = peer.getOSName(); + + if (osName != null && !"".equals(osName.trim())) { //$NON-NLS-1$ + builder.append(" [" + osName.trim() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + String ip = peer.getAttributes().get(IPeer.ATTR_IP_HOST); + String port = peer.getAttributes().get(IPeer.ATTR_IP_PORT); + + if (ip != null && !"".equals(ip.trim())) { //$NON-NLS-1$ + builder.append(" @ "); //$NON-NLS-1$ + builder.append(ip.trim()); + + if (port != null && !"".equals(port.trim()) && !"1534".equals(port.trim())) { //$NON-NLS-1$ //$NON-NLS-2$ + builder.append(":"); //$NON-NLS-1$ + builder.append(port.trim()); + } + } + + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/ModelListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/ModelListener.java new file mode 100644 index 000000000..feba68e58 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/ModelListener.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.navigator; + +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.ILocatorModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.listener.ModelAdapter; +import org.eclipse.tm.te.ui.views.interfaces.IUIConstants; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.navigator.CommonNavigator; +import org.eclipse.ui.navigator.CommonViewer; + + +/** + * Target Exploer: TCF locator model listener implementation. + */ +public class ModelListener extends ModelAdapter { + private final ILocatorModel fParentModel; + + /** + * Constructor. + * + */ + public ModelListener(ILocatorModel parent) { + assert parent != null; + fParentModel = parent; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.listener.ModelAdapter#locatorModelChanged(org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel) + */ + @Override + public void locatorModelChanged(final ILocatorModel model) { + if (fParentModel.equals(model)) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + CommonViewer viewer = getViewer(); + if (viewer != null) viewer.refresh(); + } + }); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.locator.core.listener.ModelAdapter#peerModelChanged(org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.ILocatorModel, org.eclipse.tm.te.tcf.locator.core.interfaces.nodes.IPeerModel) + */ + @Override + public void peerModelChanged(final ILocatorModel model, final IPeerModel peer) { + if (fParentModel.equals(model)) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + CommonViewer viewer = getViewer(); + if (viewer != null) viewer.refresh(peer); + } + }); + } + } + + /** + * Get the common viewer used by the Target Explorer view instance. + * + * @return The common viewer or <code>null</code> + */ + protected CommonViewer getViewer() { + if (PlatformUI.getWorkbench() != null && PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null + && PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() != null) { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IViewPart part = page.findView(IUIConstants.ID_EXPLORER); + if (part instanceof CommonNavigator) { + return ((CommonNavigator)part).getCommonViewer(); + } + } + + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/Sorter.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/Sorter.java new file mode 100644 index 000000000..0c342c5ca --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/Sorter.java @@ -0,0 +1,205 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.navigator; + +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jface.viewers.ContentViewer; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.TreePathViewerSorter; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Tree; + +/** + * Target Explorer: Common sorter implementation. + */ +public class Sorter extends TreePathViewerSorter { + private final ILabelProvider fLabelProvider = new LabelProviderDelegate(); + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) { + return doCompare(e1, e2, doGetSortColumnLabel(viewer), doGetSortColumnIndex(viewer) , doDetermineInverter(viewer)); + } + return super.compare(viewer, e1, e2); + } + + /** + * Returns the text to compare for the given node and column index. + * + * @param node The node or <code>null</code>. + * @param index The column index or <code>-1</code>. + * + * @return The text for the given node and column index or <code>null</code>. + */ + protected String doGetText(Object node, int index) { + if (node != null) { + return fLabelProvider.getText(node); + } + return null; + } + + /** + * Return the label provider associated with the specified viewer. + * + * @param viewer The viewer or <code>null</code>. + * @return The label provider or <code>null</code>. + */ + protected ILabelProvider doGetLabelProvider(Viewer viewer) { + if (viewer instanceof ContentViewer) { + IBaseLabelProvider candidate = ((ContentViewer)viewer).getLabelProvider(); + if (candidate instanceof ILabelProvider) return (ILabelProvider)candidate; + } + return null; + } + + /** + * Determine if or if not the sort direction needs to be inverted. + * + * @param viewer The viewer or <code>null</code>. + * @return <code>1</code> for original sort order, or <code>-1</code> for inverted sort order. + */ + protected int doDetermineInverter(Viewer viewer) { + int inverter = 1; + + // Viewer must be of type TreeViewer and the tree must not be disposed yet + if (viewer instanceof TreeViewer && ((TreeViewer)viewer).getTree() != null) { + Tree tree = ((TreeViewer)viewer).getTree(); + if (!tree.isDisposed() && tree.getSortDirection() == SWT.DOWN) inverter = -1; + } + + return inverter; + } + + /** + * Return the label of the sort column of the given viewer. + * + * @param viewer The viewer or <code>null</code>. + * @return The label of the sort column or an empty string. + */ + protected String doGetSortColumnLabel(Viewer viewer) { + // Viewer must be of type TreeViewer and the tree must not be disposed yet + if (viewer instanceof TreeViewer && ((TreeViewer)viewer).getTree() != null && !((TreeViewer)viewer).getTree().isDisposed()) { + Tree tree = ((TreeViewer)viewer).getTree(); + return tree.getSortColumn() != null ? tree.getSortColumn().getText() : ""; //$NON-NLS-1$ + } + return ""; //$NON-NLS-1$ + } + + /** + * Return the index of the sort column of the given viewer. + * + * @param viewer The viewer or <code>null</code>. + * @return The index of the sort column or <code>-1</code>. + */ + protected int doGetSortColumnIndex(Viewer viewer) { + if (viewer instanceof TreeViewer && ((TreeViewer)viewer).getTree() != null && !((TreeViewer)viewer).getTree().isDisposed()) { + Tree tree = ((TreeViewer)viewer).getTree(); + return tree.getSortColumn() != null ? Arrays.asList(tree.getColumns()).indexOf(tree.getSortColumn()) : -1; + } + return -1; + } + + /** + * Compare the given model nodes by the given sort column and inverter. + * + * @param node1 The first node or <code>null</code>. + * @param node2 The second node or <code>null</code>. + * @param sortColumn The sort column text or <code>null</code>. + * @param index The sort column index or <code>-1</code>. + * @param inverter The inverter. + * + * @return The compare result. + */ + @SuppressWarnings("unchecked") + protected int doCompare(Object node1, Object node2, String sortColumn, int index, int inverter) { + if (node1 == null && node2 == null) return 0; + if (node1 != null && node2 == null) return 1; + if (node1 == null && node2 != null) return -1; + + // Get the labels + String text1 = doGetText(node1, index); + String text2 = doGetText(node2, index); + + // The tree sorts not strictly alphabetical. First comes entries starting with numbers, + // second entries starting with uppercase and than all the rest. Additional, if a label contains + // uppercase characters, it is sorted in before any labels being lowercase only. + if (text1.length() > 0 && text2.length() > 0) { + // Get the first characters of both + char c1 = text1.charAt(0); + char c2 = text2.charAt(0); + + if (Character.isDigit(c1) || Character.isDigit(c2)) { + // Check on the differences. If both are digits, the standard compare will do it + if (Character.isDigit(c1) && !Character.isDigit(c2)) return -1 * inverter; + if (!Character.isDigit(c1) && Character.isDigit(c2)) return 1 * inverter; + } + + if (Character.isUpperCase(c1) || Character.isUpperCase(c2)) { + // Check on the differences. If both are uppercase characters, the standard compare will do it + if (Character.isUpperCase(c1) && !Character.isUpperCase(c2)) return -1 * inverter; + if (!Character.isUpperCase(c1) && Character.isUpperCase(c2)) return 1 * inverter; + } + + Matcher m1 = Pattern.compile("(\\D+)(\\d+)").matcher(text1); //$NON-NLS-1$ + Matcher m2 = Pattern.compile("(\\D+)(\\d+)").matcher(text2); //$NON-NLS-1$ + if (m1.matches() && m2.matches()) { + String p11 = m1.group(1); + String p12 = m1.group(2); + + String p21 = m2.group(1); + String p22 = m2.group(2); + + if (p11 != null && p11.equals(p21)) { + // Compare the second parts as number + try { + int result = 0; + long l1 = Long.parseLong(p12); + long l2 = Long.parseLong(p22); + + if (l1 > l2) result = 1; + if (l1 < l2) result = -1; + + return result; + } catch (NumberFormatException e) { /* ignored on purpose */ } + } + } + + if (text1.matches(".*[A-Z]+.*") || text2.matches(".*[A-Z]+.*")) { //$NON-NLS-1$ //$NON-NLS-2$ + if (text1.matches(".*[A-Z]+.*") && !text2.matches(".*[A-Z]+.*")) return -1 * inverter; //$NON-NLS-1$ //$NON-NLS-2$ + if (!text1.matches(".*[A-Z]+.*") && text2.matches(".*[A-Z]+.*")) return 1 * inverter; //$NON-NLS-1$ //$NON-NLS-2$ + + // Additionally, it even depends on the position of the first uppercase + // character if both strings contains them :-( + int minLength = Math.min(text1.length(), text2.length()); + for (int i = 0; i < minLength; i++) { + char ch1 = text1.charAt(i); + char ch2 = text2.charAt(i); + + if (Character.isUpperCase(ch1) && !Character.isUpperCase(ch2)) return -1 * inverter; + if (!Character.isUpperCase(ch1) && Character.isUpperCase(ch2)) return 1 * inverter; + // If both are uppercase, we break the loop and compare as usual + if (Character.isUpperCase(ch1) && Character.isUpperCase(ch2)) break; + } + } + } + + // Compare the text alphabetical + return getComparator().compare(text1, text2) * inverter; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/images/PeerImageDescriptor.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/images/PeerImageDescriptor.java new file mode 100644 index 000000000..7ecfe435a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/navigator/images/PeerImageDescriptor.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.navigator.images; + +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModelProperties; +import org.eclipse.tm.te.tcf.ui.internal.registries.InternalImageRegistry; +import org.eclipse.tm.te.ui.images.AbstractImageDescriptor; + + +/** + * Target Explorer: Peer model node image descriptor implementation. + */ +public class PeerImageDescriptor extends AbstractImageDescriptor { + // the base image to decorate with overlays + private Image fBaseImage; + // the image size + private Point fImageSize; + + // Flags representing the object states to decorate + private int fState; + + /** + * Constructor. + */ + public PeerImageDescriptor(final ImageRegistry registry, final Image baseImage, final IPeerModel node) { + super(registry); + + fBaseImage = baseImage; + fImageSize = new Point(fBaseImage.getImageData().width, fBaseImage.getImageData().height); + + // Determine the current object state to decorate + if (Protocol.isDispatchThread()) { + initialize(node); + } else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + initialize(node); + } + }); + } + + // build up the key for the image registry + defineKey(fBaseImage.hashCode()); + } + + /** + * Initialize the image descriptor from the peer model. + * + * @param node The peer model. Must be not <code>null</code>. + */ + protected void initialize(IPeerModel node) { + assert Protocol.isDispatchThread() && node != null; + + fState = node.getIntProperty(IPeerModelProperties.PROP_STATE); + } + + protected void defineKey(int hashCode) { + String key = "PMID:" + //$NON-NLS-1$ + hashCode + ":" + //$NON-NLS-1$ + fState; + + setKey(key); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.resource.CompositeImageDescriptor#drawCompositeImage(int, int) + */ + @Override + protected void drawCompositeImage(int width, int height) { + drawCentered(fBaseImage, width, height); + + if (fState == IPeerModelProperties.STATE_UNKNOWN) { /* unknown */ + drawBottomRight(InternalImageRegistry.OVERLAY_Grey); + } + else if (fState == IPeerModelProperties.STATE_REACHABLE) { /* not connected, but reachable */ + drawBottomRight(InternalImageRegistry.OVERLAY_Gold); + } + else if (fState == IPeerModelProperties.STATE_CONNECTED) { /* connected */ + drawBottomRight(InternalImageRegistry.OVERLAY_Green); + } + else if (fState == IPeerModelProperties.STATE_NOT_REACHABLE) { /* not connected, not reachable */ + drawBottomRight(InternalImageRegistry.OVERLAY_Red); + } + else if (fState == IPeerModelProperties.STATE_ERROR) { /* not connected, error */ + drawBottomRight(InternalImageRegistry.OVERLAY_RedX); + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.resource.CompositeImageDescriptor#getSize() + */ + @Override + protected Point getSize() { + return fImageSize; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.ide.util.ui.AbstractImageDescriptor#getBaseImage() + */ + @Override + protected Image getBaseImage() { + return fBaseImage; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/nls/Messages.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/nls/Messages.java new file mode 100644 index 000000000..e7267fb35 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/nls/Messages.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.nls; + +import java.lang.reflect.Field; + +import org.eclipse.osgi.util.NLS; + +/** + * Target Explorer: TCF UI Plug-in externalized strings management. + */ +public class Messages extends NLS { + + // The plug-in resource bundle name + private static final String BUNDLE_NAME = "org.eclipse.tm.te.tcf.ui.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 NodePropertiesContentProvider_peerNode_sectionTitle; + + public static String NodePropertiesLabelProvider_state; + public static String NodePropertiesLabelProvider_state__1; + public static String NodePropertiesLabelProvider_state_0; + public static String NodePropertiesLabelProvider_state_1; + public static String NodePropertiesLabelProvider_state_2; + public static String NodePropertiesLabelProvider_state_3; + + public static String NodePropertiesLabelProvider_lastScannerError; + + public static String NodePropertiesLabelProvider_services_local; + public static String NodePropertiesLabelProvider_services_remote; + + public static String AddPeerDialog_title; + + public static String TransportTypeControl_label; + + public static String AgentHostControl_label; + + public static String AgentPortControl_label; + + public static String PeerIdControl_label; + + public static String PeerNameControl_label; +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/nls/Messages.properties new file mode 100644 index 000000000..94fdbfa19 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/nls/Messages.properties @@ -0,0 +1,30 @@ +# +# org.eclipse.tm.te.tcf.ui +# Externalized Strings. +# + +NodePropertiesContentProvider_peerNode_sectionTitle=Peer + +NodePropertiesLabelProvider_state=Link State +NodePropertiesLabelProvider_state__1=Unknown +NodePropertiesLabelProvider_state_0=Reachable +NodePropertiesLabelProvider_state_1=Communicating +NodePropertiesLabelProvider_state_2=Not Reachable. Connection attempt timed out. +NodePropertiesLabelProvider_state_3=Not Reachable. Connection attempt failed. + +NodePropertiesLabelProvider_lastScannerError=Communication failed. Possible cause: + +NodePropertiesLabelProvider_services_local=Local Services +NodePropertiesLabelProvider_services_remote=Remote Services + +AddPeerDialog_title=Add New Peer + +TransportTypeControl_label=Type: + +AgentHostControl_label=Host: + +AgentPortControl_label=Port: + +PeerIdControl_label=ID: + +PeerNameControl_label=Name: diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/registries/InternalImageRegistry.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/registries/InternalImageRegistry.java new file mode 100644 index 000000000..c5bae59a2 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/internal/registries/InternalImageRegistry.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.internal.registries; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.Plugin; +import org.eclipse.tm.te.ui.images.AbstractImageRegistry; + + +/** + * Target Explorer: TCF UI plugin image registry. + */ +public class InternalImageRegistry extends AbstractImageRegistry { + private static List<Object[]> fStore = new ArrayList<Object[]>(); + + // declare all keys down here + public static final String OBJ_Target = declareLocalImage("obj16", "target.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + + // Overlays + public final static String OVERLAY_Gold = declareLocalImage("ovr16", "gold_ovr.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public final static String OVERLAY_Green = declareLocalImage("ovr16", "green_ovr.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public final static String OVERLAY_Grey = declareLocalImage("ovr16", "grey_ovr.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public final static String OVERLAY_Red = declareLocalImage("ovr16", "red_ovr.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public final static String OVERLAY_RedX = declareLocalImage("ovr16", "redX_ovr.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + + // external eclipse icons not reachable using ISharedImages + + /** + * Constructor. + * + * @param plugin The plugin descriptor the image registry is created for. + */ + public InternalImageRegistry(Plugin plugin) { + super(plugin); + } + + /** + * Initialize image registry with all keys known yet. + */ + public void initialize() { + for (Iterator<Object[]> iter = fStore.iterator(); iter.hasNext();) { + Object[] element = iter.next(); + if (element.length == 3) { + localImage((String)element[0], (String)element[1], (String)element[2]); + } + else if (element.length > 3){ + externalImage((String)element[0], (String)element[1], (String[])element[2], (String)element[3]); + } + } + } + + /** + * Declare a locally stored image to the image registry. + */ + static String declareLocalImage(String dir, String name) { + List<Object> registryObject = new ArrayList<Object>(); + registryObject.add(dir); + registryObject.add(name); + String key = name + "_" + registryObject.hashCode(); //$NON-NLS-1$ + registryObject.add(0, key); + fStore.add(registryObject.toArray()); + return key; + } + + /** + * Declare a externally stored image to the image registry. + */ + static String declareExternalImage(String plugin, String[] dirs, String name) { + List<Object> registryObject = new ArrayList<Object>(); + registryObject.add(plugin); + registryObject.add(dirs); + registryObject.add(name); + String key = name + "_" + registryObject.hashCode(); //$NON-NLS-1$ + registryObject.add(0, key); + fStore.add(registryObject.toArray()); + return key; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/tables/NodePropertiesContentProvider.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/tables/NodePropertiesContentProvider.java new file mode 100644 index 000000000..ae7d5d9c6 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/tables/NodePropertiesContentProvider.java @@ -0,0 +1,160 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.tables; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.widgets.Control; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModelProperties; +import org.eclipse.tm.te.tcf.ui.internal.nls.Messages; +import org.eclipse.tm.te.ui.tables.TableNode; +import org.eclipse.ui.forms.widgets.Section; + + +/** + * Target Explorer: TCF node properties table content provider implementation. + */ +public class NodePropertiesContentProvider implements IStructuredContentProvider { + + /** + * The list of properties to filter out and not to show within the table. + */ + protected final static String[] FILTERED_PROPERTIES = new String[] { + "name", "typeLabel", //$NON-NLS-1$ //$NON-NLS-2$ + "instance", "childrenQueried", //$NON-NLS-1$ //$NON-NLS-2$ + IPeerModelProperties.PROP_CHANNEL_REF_COUNTER, + "hasTabularProperties" //$NON-NLS-1$ + }; + + // Flag to control if the content provide may update the parent section title + private final boolean fUpdateParentSectionTitle; + + /** + * Constructor. + * + * @param updateParentSectionTitle Specify <code>true</code> to allow the content provider to update + * the parent section title, <code>false</code> if no title update is desired. + */ + public NodePropertiesContentProvider(boolean updateParentSectionTitle) { + fUpdateParentSectionTitle = updateParentSectionTitle; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + */ + public Object[] getElements(final Object inputElement) { + List<TableNode> nodes = new ArrayList<TableNode>(); + + if (inputElement instanceof IPeerModel) { + TableNode lastErrorNode = null; + + // Get all custom properties of the node + final Map<String, Object> properties = new HashMap<String, Object>(); + // And get all native properties of the peer + if (Protocol.isDispatchThread()) { + properties.putAll(((IPeerModel)inputElement).getProperties()); + properties.putAll(((IPeerModel)inputElement).getPeer().getAttributes()); + } else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + properties.putAll(((IPeerModel)inputElement).getProperties()); + properties.putAll(((IPeerModel)inputElement).getPeer().getAttributes()); + } + }); + } + + for (String name : properties.keySet()) { + // Check if the property is filtered + if (name.endsWith(".silent") || Arrays.asList(FILTERED_PROPERTIES).contains(name)) continue; //$NON-NLS-1$ + // Create the properties node + TableNode propertiesNode = new TableNode(name, properties.get(name) != null ? properties.get(name).toString() : ""); //$NON-NLS-1$ + if (!IPeerModelProperties.PROP_LAST_SCANNER_ERROR.equals(name)) nodes.add(propertiesNode); + else lastErrorNode = propertiesNode; + } + + if (lastErrorNode != null) { + // Add an empty line before the error + TableNode propertiesNode = new TableNode("", ""); //$NON-NLS-1$ //$NON-NLS-2$ + nodes.add(propertiesNode); + nodes.add(lastErrorNode); + } + } + + return nodes.toArray(new TableNode[nodes.size()]); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // Do nothing if we shall not update the section title + if (!fUpdateParentSectionTitle) return; + + String sectionTitle = null; + Object element = null; + + // If the input is a tree selection, extract the element from the tree path + if (newInput instanceof ITreeSelection && !((ITreeSelection)newInput).isEmpty()) { + // Cast to the correct type + ITreeSelection selection = (ITreeSelection)newInput; + // Get the selected tree pathes + TreePath[] pathes = selection.getPaths(); + // If there are more than one elements selected, we care only about the first path + TreePath path = pathes.length > 0 ? pathes[0] : null; + // Get the last element within the tree path + element = path != null ? path.getLastSegment() : null; + } + + // If the input is a peer model node, set it directly + if (newInput instanceof IPeerModel) element = newInput; + + // Determine the section header text + if (element instanceof IPeerModel) { + sectionTitle = NLS.bind(org.eclipse.tm.te.ui.nls.Messages.NodePropertiesTableControl_section_title, Messages.NodePropertiesContentProvider_peerNode_sectionTitle); + } + + // Set the standard (no selection) section title if none could be determined + if (sectionTitle == null || "".equals(sectionTitle.trim())) sectionTitle = org.eclipse.tm.te.ui.nls.Messages.NodePropertiesTableControl_section_title_noSelection; //$NON-NLS-1$ + // Stretch to a length of 40 characters to make sure the title can be changed + // to hold and show text up to this length + while (sectionTitle.length() < 40) sectionTitle += " "; //$NON-NLS-1$ + + // Find the parent section the node properties tables is embedded in + Control control = viewer.getControl(); + while (control != null && !control.isDisposed()) { + if (control instanceof Section) { + Section section = (Section)control; + // We cannot get access to the Label control used to set the text, so just catch the + // probably SWTException + try { section.setText(sectionTitle); } catch(SWTException e) { /* ignored on purpose */ } + break; + } + control = control.getParent(); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/tables/NodePropertiesLabelProvider.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/tables/NodePropertiesLabelProvider.java new file mode 100644 index 000000000..c201c0f0c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/tables/NodePropertiesLabelProvider.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.tables; + +import org.eclipse.jface.viewers.ITableColorProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModelProperties; +import org.eclipse.tm.te.tcf.ui.internal.nls.Messages; +import org.eclipse.tm.te.ui.tables.TableNode; + + +/** + * Target Explorer: TCF node properties table label provider implementation. + */ +public class NodePropertiesLabelProvider extends LabelProvider implements ITableLabelProvider, ITableColorProvider { + // Reference to the parent table viewer + private final TableViewer fParentViewer; + + /** + * Constructor. + * + * @param viewer The table viewer or <code>null</code>. + */ + public NodePropertiesLabelProvider(TableViewer viewer) { + super(); + fParentViewer = viewer; + } + + /** + * Returns the parent table viewer instance. + * + * @return The parent table viewer or <code>null</code>. + */ + protected final TableViewer getParentViewer() { + return fParentViewer; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.datasource.controls.tables.TableLabelProvider#getColumnText(org.eclipse.tm.te.tcf.core.runtime.model.interfaces.IModelNode, int) + */ + public String getColumnText(Object element, int columnIndex) { + assert element != null; + + String label = null; + + if (element instanceof TableNode) { + switch (columnIndex) { + case 0: + label = ((TableNode)element).name; + break; + case 1: + label = ((TableNode)element).value; + break; + } + + if (label != null) { + if (IPeerModelProperties.PROP_LAST_SCANNER_ERROR.equals(label)) { + label = Messages.NodePropertiesLabelProvider_lastScannerError; + } else if (IPeerModelProperties.PROP_STATE.equals(label)) { + label = Messages.NodePropertiesLabelProvider_state; + } else if (IPeerModelProperties.PROP_LOCAL_SERVICES.equals(label)) { + label = Messages.NodePropertiesLabelProvider_services_local; + } else if (IPeerModelProperties.PROP_REMOTE_SERVICES.equals(label)) { + label = Messages.NodePropertiesLabelProvider_services_remote; + } else if (columnIndex == 1 && IPeerModelProperties.PROP_STATE.equals(((TableNode)element).name)) { + label = Messages.getString("NodePropertiesLabelProvider_state_" + label.replace('-', '_')); //$NON-NLS-1$ + } + } + } + + return label; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int) + */ + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITableColorProvider#getForeground(java.lang.Object, int) + */ + public Color getForeground(Object element, int columnIndex) { + if (element instanceof TableNode && IPeerModelProperties.PROP_LAST_SCANNER_ERROR.equals(((TableNode)element).name)) { + return getParentViewer().getControl().getDisplay().getSystemColor(SWT.COLOR_RED); + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITableColorProvider#getBackground(java.lang.Object, int) + */ + public Color getBackground(Object element, int columnIndex) { + return null; + } + + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/tables/NodePropertiesViewerComparator.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/tables/NodePropertiesViewerComparator.java new file mode 100644 index 000000000..157a0bc86 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.ui/src/org/eclipse/tm/te/tcf/ui/tables/NodePropertiesViewerComparator.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.tcf.ui.tables; + +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.tm.te.tcf.ui.internal.nls.Messages; +import org.eclipse.tm.te.ui.tables.TableViewerComparator; + + +/** + * Target Explorer: TCF node properties table viewer comparator implementation. + */ +public class NodePropertiesViewerComparator extends TableViewerComparator { + + /** + * Constructor. + * + * @param viewer The parent viewer. Must be not <code>null</code>. + * @param labelProvider The table label provider. Must be not <code>null</code>. + */ + public NodePropertiesViewerComparator(Viewer viewer, ITableLabelProvider labelProvider) { + super(viewer, labelProvider); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.tcf.vtl.ui.tables.TableViewerComparator#doCompare(java.lang.Object, java.lang.Object, java.lang.String, int, int) + */ + @Override + protected int doCompare(Object node1, Object node2, String sortColumn, int index, int inverter) { + if (node1 != null && node2 != null && index == 0) { + String t1 = doGetText(node1, index); + String t2 = doGetText(node2, index); + + // Special handling for empty text and last error text + if ("".equals(t1) || "".equals(t2) //$NON-NLS-1$ //$NON-NLS-2$ + || Messages.NodePropertiesLabelProvider_lastScannerError.equals(t1) + || Messages.NodePropertiesLabelProvider_lastScannerError.equals(t2)) { + if (("".equals(t1) || Messages.NodePropertiesLabelProvider_lastScannerError.equals(t1)) //$NON-NLS-1$ + && !("".equals(t2) || Messages.NodePropertiesLabelProvider_lastScannerError.equals(t2))) { //$NON-NLS-1$ + return 1; + } + if (!("".equals(t1) || Messages.NodePropertiesLabelProvider_lastScannerError.equals(t1)) //$NON-NLS-1$ + && ("".equals(t2) || Messages.NodePropertiesLabelProvider_lastScannerError.equals(t2))) { //$NON-NLS-1$ + return -1; + } + if ("".equals(t1) && Messages.NodePropertiesLabelProvider_lastScannerError.equals(t2)) { //$NON-NLS-1$ + return -1; + } + if ("".equals(t2) && Messages.NodePropertiesLabelProvider_lastScannerError.equals(t1)) { //$NON-NLS-1$ + return 1; + } + } + } + + return super.doCompare(node1, node2, sortColumn, index, inverter); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/.classpath b/target_explorer/plugins/org.eclipse.tm.te.ui.views/.classpath new file mode 100644 index 000000000..64c5e31b7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/.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/J2SE-1.5"/> + <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.tm.te.ui.views/.project b/target_explorer/plugins/org.eclipse.tm.te.ui.views/.project new file mode 100644 index 000000000..22f8a6f02 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.tm.te.ui.views</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/.settings/org.eclipse.jdt.core.prefs b/target_explorer/plugins/org.eclipse.tm.te.ui.views/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..16730451b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,77 @@ +#Wed Dec 15 14:57:08 CET 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +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.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=ignore +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=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +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.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.5 diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tm.te.ui.views/META-INF/MANIFEST.MF new file mode 100644 index 000000000..f54227fd2 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/META-INF/MANIFEST.MF @@ -0,0 +1,18 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.tm.te.ui.views;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.tm.te.ui.views.activator.UIPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0", + org.eclipse.core.expressions;bundle-version="3.4.200", + org.eclipse.ui;bundle-version="3.6.2", + org.eclipse.ui.forms;bundle-version="3.5.2", + org.eclipse.ui.navigator;bundle-version="3.5.0", + org.eclipse.tm.te.core;bundle-version="1.0.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.tm.te.ui.views.editor;version="1.0.0", + org.eclipse.tm.te.ui.views.interfaces;version="1.0.0" diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/build.properties b/target_explorer/plugins/org.eclipse.tm.te.ui.views/build.properties new file mode 100644 index 000000000..d24082bdb --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.properties,\ + plugin.xml,\ + icons/ diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/icons/eview16/editor.gif b/target_explorer/plugins/org.eclipse.tm.te.ui.views/icons/eview16/editor.gif Binary files differnew file mode 100644 index 000000000..9ca749bbd --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/icons/eview16/editor.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/icons/eview16/prop_ps.gif b/target_explorer/plugins/org.eclipse.tm.te.ui.views/icons/eview16/prop_ps.gif Binary files differnew file mode 100644 index 000000000..d11c996e5 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/icons/eview16/prop_ps.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/icons/eview16/targets_view.gif b/target_explorer/plugins/org.eclipse.tm.te.ui.views/icons/eview16/targets_view.gif Binary files differnew file mode 100644 index 000000000..9ca749bbd --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/icons/eview16/targets_view.gif diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/plugin.properties b/target_explorer/plugins/org.eclipse.tm.te.ui.views/plugin.properties new file mode 100644 index 000000000..3b97b3b7c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/plugin.properties @@ -0,0 +1,35 @@ +################################################################################## +# 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: +# Uwe Stieber (Wind River) - initial API and implementation +################################################################################## + +pluginName = Target Explorer View +providerName = Eclipse.org + +# ***** Extension Points ***** + +ExtensionPoint.editorPages.name=Target Explorer Details Editor Pages Extension Point +ExtensionPoint.editorPageBindings.name=Target Explorer Details Editor Page Bindings Extension Point + +# ***** Perspective ***** + +Perspective.name=Target Explorer + +# ***** Views ***** + +ViewCategory.name=Target Explorer Views +TargetExplorer.name=Target Explorer + +# ***** Editor ***** + +Editor.name=Target Explorer Details Editor + +# ***** Command and menu contributions ***** + +PropertiesAction.label=&Properties +PropertiesAction.tooltip=Show Properties of Selection diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/plugin.xml b/target_explorer/plugins/org.eclipse.tm.te.ui.views/plugin.xml new file mode 100644 index 000000000..81443abd3 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/plugin.xml @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> + <extension-point id="editorPageBindings" name="%ExtensionPoint.editorPageBindings.name" schema="schema/editorPageBindings.exsd"/> + <extension-point id="editorPages" name="%ExtensionPoint.editorPages.name" schema="schema/editorPages.exsd"/> + +<!-- Common Navigator contributions --> + <extension point="org.eclipse.ui.navigator.viewer"> + <viewer + helpContext="org.eclipse.tm.te.ui.views.TargetExplorer" + viewerId="org.eclipse.tm.te.ui.views.TargetExplorer"> + <popupMenu + id="org.eclipse.tm.te.ui.views.TargetExplorer#Popup" + allowsPlatformContributions="true"> + <insertionPoint name="group.new" separator="true"/> + <insertionPoint name="group.goto"/> + <insertionPoint name="group.expandto" separator="true"/> + <insertionPoint name="group.expand"/> + <insertionPoint name="group.open" separator="true"/> + <insertionPoint name="group.openWith"/> + <insertionPoint name="group.connect" separator="true"/> + <insertionPoint name="group.symbols" separator="true"/> + <insertionPoint name="group.symbols.rd"/> + <insertionPoint name="group.symbols.loadunload"/> + <insertionPoint name="group.symbols.additions"/> + <insertionPoint name="group.launch" separator="true"/> + <insertionPoint name="group.launch.rundebug"/> + <insertionPoint name="group.launch.modes"/> + <insertionPoint name="group.launch.additions"/> + <insertionPoint name="group.show" separator="true"/> + <insertionPoint name="group.edit" separator="true"/> + <insertionPoint name="group.delete"/> + <insertionPoint name="group.build" separator="true"/> + <insertionPoint name="group.refresh" separator="true"/> + <insertionPoint name="group.reorganize"/> + <insertionPoint name="group.reorder"/> + <insertionPoint name="group.port"/> + <insertionPoint name="group.generate" separator="true"/> + <insertionPoint name="group.search" separator="true"/> + <insertionPoint name="group.connection" separator="true"/> + <insertionPoint name="group.operations" separator="true"/> + <insertionPoint name="group.analysis" separator="true"/> + <insertionPoint name="additions" separator="true"/> + <insertionPoint name="group.properties" separator="true"/> + </popupMenu> + <options> + <property + name="org.eclipse.ui.navigator.hideLinkWithEditorAction" + value="true"> + </property> + </options> + </viewer> + </extension> + +<!-- View contributions --> + <extension point="org.eclipse.ui.views"> + <category + id="org.eclipse.tm.te.ui.views.category" + name="%ViewCategory.name"> + </category> + <view + category="org.eclipse.tm.te.ui.views.category" + class="org.eclipse.tm.te.ui.views.internal.View" + icon="icons/eview16/targets_view.gif" + id="org.eclipse.tm.te.ui.views.TargetExplorer" + name="%TargetExplorer.name" + restorable="true"> + </view> + </extension> + +<!-- Target Explorer Perspective --> + <extension point="org.eclipse.ui.perspectives"> + <perspective + class="org.eclipse.tm.te.ui.views.perspective.PerspectiveFactory" + icon="icons/eview16/editor.gif" + id="org.eclipse.tm.te.ui.perspective" + name="%Perspective.name"> + </perspective> + </extension> + +<!-- Perspective contributions --> + <extension point="org.eclipse.ui.perspectiveExtensions"> + <perspectiveExtension targetID="org.eclipse.tm.te.ui.perspective"> + <!-- Run/Debug actions should be available --> + <actionSet id="org.eclipse.debug.ui.launchActionSet"/> + <!-- Register the view shortcuts --> + <viewShortcut id="org.eclipse.tm.te.ui.views.TargetExplorer"/> + </perspectiveExtension> + </extension> + +<!-- Editor contributions --> + <extension point="org.eclipse.ui.editors"> + <editor + class="org.eclipse.tm.te.ui.views.internal.editor.Editor" + default="false" + icon="icons/eview16/prop_ps.gif" + id="org.eclipse.tm.te.ui.view.Editor" + name="%Editor.name"> + </editor> + </extension> + +<!-- Target Explorer menu contributions --> + <extension point="org.eclipse.ui.menus"> + <menuContribution locationURI="popup:org.eclipse.tm.te.ui.views.TargetExplorer#Popup?after=group.properties"> + <command + commandId="org.eclipse.ui.file.properties" + helpContextId="org.eclipse.tm.te.ui.views.command_Properties" + id="properties" + label="%PropertiesAction.label" + tooltip="%PropertiesAction.tooltip"> + <visibleWhen> + <with variable="selection"> + <count value="1"/> + <iterate operator="and" ifEmpty="false"> + <test property="org.eclipse.tm.te.ui.views.hasApplicableEditorBindings" value="true"/> + </iterate> + </with> + </visibleWhen> + </command> + </menuContribution> + </extension> + +<!-- Handler contributions --> + <extension point="org.eclipse.ui.handlers"> + <handler + commandId="org.eclipse.ui.file.properties" + class="org.eclipse.tm.te.ui.views.internal.targets.handler.PropertiesCommandHandler"> + <enabledWhen> + <with variable="selection"> + <count value="1"/> + </with> + </enabledWhen> + <activeWhen> + <with variable="activePartId"> + <equals value="org.eclipse.tm.te.ui.views.TargetExplorer"/> + </with> + </activeWhen> + </handler> + </extension> + +<!-- Eclipse core expressions property tester --> + <extension point="org.eclipse.core.expressions.propertyTesters"> + <propertyTester + class="org.eclipse.tm.te.ui.views.internal.expressions.EditorPropertyTester" + id="org.eclipse.tm.te.ui.views.EditorPropertyTester" + namespace="org.eclipse.tm.te.ui.views" + properties="hasApplicableEditorBindings" + type="java.lang.Object"> + </propertyTester> + </extension> + +</plugin> diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/schema/editorPageBindings.exsd b/target_explorer/plugins/org.eclipse.tm.te.ui.views/schema/editorPageBindings.exsd new file mode 100644 index 000000000..a7bc73d8f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/schema/editorPageBindings.exsd @@ -0,0 +1,163 @@ +<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.tm.te.ui.views" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="org.eclipse.tm.te.ui.views" id="editorPageBindings" name="Target Explorer Editor Page Bindings Extension Point"/>
+ </appinfo>
+ <documentation>
+ This extension point is used to declare the Target Explorer editor page bindings.
+<p>
+<b>Note:</b> For the enablement expression evaluation, note that the default variable and the "activeEditorInput" variable are the same and non-iterable.
+ </documentation>
+ </annotation>
+
+ <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="editorPageBinding" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="editorPageBinding">
+ <annotation>
+ <documentation>
+ Declares a Target Explorer editor page binding.
+ </documentation>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="enablement" minOccurs="0" maxOccurs="1"/>
+ </sequence>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ The unique id of the editor page binding contribution.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="pageId" type="string" use="required">
+ <annotation>
+ <documentation>
+ The unique id of the referenced editor page.
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="identifier" basedOn="org.eclipse.tm.te.ui.views.editorPages/editorPage/@id"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ <attribute name="insertBefore">
+ <annotation>
+ <documentation>
+ The id of the page this page shall be inserted before, or "first" to insert it at the beginning of the stack. If "insertBefore" is specified non-empty, it will eclipse the "insertAfter" attribute. If neither "insertBefore" or "insertAfter" is specified, the page will be inserted at the end of the stack.
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="identifier" basedOn="org.eclipse.tm.te.ui.views.editorPages/editorPage/@id"/>
+ </appinfo>
+ </annotation>
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="first">
+ </enumeration>
+ </restriction>
+ </simpleType>
+ </attribute>
+ <attribute name="insertAfter">
+ <annotation>
+ <documentation>
+ The id of the page this page shall be inserted after, or "last" to insert it at the end of the stack. If "insertBefore" is specified non-empty, it will eclipse the "insertAfter" attribute. If neither "insertBefore" or "insertAfter" is specified, the page will be inserted at the end of the stack.
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="identifier" basedOn="org.eclipse.te.ui.views.editorPages/editorPage/@id"/>
+ </appinfo>
+ </annotation>
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="last">
+ </enumeration>
+ </restriction>
+ </simpleType>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="since"/>
+ </appinfo>
+ <documentation>
+ Target Explorer 1.0.0
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="examples"/>
+ </appinfo>
+ <documentation>
+ <pre>
+ <extension point="org.eclipse.tm.te.ui.views.editorPageBindings">
+ <editorPageBinding
+ id="org.eclipse.tm.te.tcf.binding.TcfPeerPropertiesPage"
+ pageId="org.eclipse.tm.te.tcf.ui.TcfPeerPropertiesPage">
+ <enablement>
+ <with variable="activeEditorInput">
+ ...
+ </with>
+ </enablement>
+ </editorPageBinding>
+ </extension>
+</pre>
+ </documentation>
+ </annotation>
+
+
+
+ <annotation>
+ <appinfo>
+ <meta.section type="copyright"/>
+ </appinfo>
+ <documentation>
+ 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.
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/schema/editorPages.exsd b/target_explorer/plugins/org.eclipse.tm.te.ui.views/schema/editorPages.exsd new file mode 100644 index 000000000..6c76732ae --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/schema/editorPages.exsd @@ -0,0 +1,147 @@ +<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.tm.te.ui.views" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="org.eclipse.tm.te.ui.views" id="editorPages" name="Target Explorer Editor Pages Extension Point"/>
+ </appinfo>
+ <documentation>
+ This extension point is used to allow the contribution of new Target Explorer editor pages.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="editorPage" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="editorPage">
+ <annotation>
+ <documentation>
+ Declares a Target Explorer editor page contribution.
+ </documentation>
+ </annotation>
+ <complexType>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ The unique editor page id.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+ A translatable name that will be used in the UI for this editor page.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ The class that implements <code>org.eclipse.tm.te.ui.views.interfaces.IEditorPage</code> or extends <code>org.eclipse.tm.te.ui.views.editor.AbstractEditorPage</code>.
+<p>
+The editor page implementation class must be specified either by the class attribute or the class child element!
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn="org.eclipse.tm.te.views.editor.AbstractEditorPage:org.eclipse.tm.te.ui.views.interfaces.IEditorPage"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ <attribute name="icon" type="string">
+ <annotation>
+ <documentation>
+ A relative name of the icon that will be used for the editor page.
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="resource"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="since"/>
+ </appinfo>
+ <documentation>
+ Target Explorer 1.0.0
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="examples"/>
+ </appinfo>
+ <documentation>
+ <pre>
+ <extension point="org.eclipse.tm.te.ui.views.editorPages">
+ <editorPage
+ class="org.eclipse.tm.te.tcf.ui.internal.TcfPeerPropertiesPage"
+ id="org.eclipse.tm.te.tcf.ui.TcfPeerPropertiesPage"
+ label="TCF Peer Properties Editor Page">
+ </editorPage>
+ </extension>
+</pre>
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="apiinfo"/>
+ </appinfo>
+ <documentation>
+ Plug-ins that want to extend this extension point, the referenced class must implement <samp>org.eclipse.tm.te.ui.views.interfaces.IEditorPage</samp> interface.
+ </documentation>
+ </annotation>
+
+
+ <annotation>
+ <appinfo>
+ <meta.section type="copyright"/>
+ </appinfo>
+ <documentation>
+ 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.
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/activator/UIPlugin.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/activator/UIPlugin.java new file mode 100644 index 000000000..dd9063d2b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/activator/UIPlugin.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.activator; + +import java.net.URL; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm.te.ui.views.interfaces.ImageConsts; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + + +/** + * The activator class controls the plug-in life cycle + */ +public class UIPlugin extends AbstractUIPlugin { + + // The shared instance + private static UIPlugin plugin; + + /** + * The constructor + */ + public UIPlugin() { + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static UIPlugin 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; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#initializeImageRegistry(org.eclipse.jface.resource.ImageRegistry) + */ + @Override + protected void initializeImageRegistry(ImageRegistry registry) { + URL url = UIPlugin.getDefault().getBundle().getEntry(ImageConsts.IMAGE_DIR_ROOT + ImageConsts.IMAGE_EDITOR + "prop_ps.gif"); //$NON-NLS-1$ + registry.put(ImageConsts.IMAGE_EDITOR, ImageDescriptor.createFromURL(url)); + } + + /** + * Loads the image registered under the specified key from the image + * registry and returns the <code>Image</code> object instance. + * + * @param key The key the image is registered with. + * @return The <code>Image</code> object instance or <code>null</code>. + */ + public static Image getImage(String key) { + return getDefault().getImageRegistry().get(key); + } + + /** + * Loads the image registered under the specified key from the image + * registry and returns the <code>ImageDescriptor</code> object instance. + * + * @param key The key the image is registered with. + * @return The <code>ImageDescriptor</code> object instance or <code>null</code>. + */ + public static ImageDescriptor getImageDescriptor(String key) { + return getDefault().getImageRegistry().getDescriptor(key); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/editor/AbstractEditorPage.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/editor/AbstractEditorPage.java new file mode 100644 index 000000000..b0771e58c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/editor/AbstractEditorPage.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.editor; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tm.te.core.nls.Messages; +import org.eclipse.tm.te.ui.views.activator.UIPlugin; +import org.eclipse.tm.te.ui.views.interfaces.IEditorPage; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.forms.editor.FormPage; + + +/** + * Target Explorer: Abstract details editor page implementation. + */ +public abstract class AbstractEditorPage extends FormPage implements IEditorPage { + // The unique page id + private String fId; + + /** + * Constructor. + */ + public AbstractEditorPage() { + super("", ""); // //$NON-NLS-1$ //$NON-NLS-2$ + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.EditorPart#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object) + */ + @Override + public void setInitializationData(IConfigurationElement config, String propertyName, Object data) { + super.setInitializationData(config, propertyName, data); + + if (config != null) { + // Initialize the id field by reading the <id> extension attribute. + // Throws an exception if the id is empty or null. + fId = config.getAttribute("id"); //$NON-NLS-1$ + if (fId == null || fId.trim().length() == 0) { + IStatus status = new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), + NLS.bind(Messages.Extension_error_missingRequiredAttribute, "id", config.getContributor().getName())); //$NON-NLS-1$ + UIPlugin.getDefault().getLog().log(status); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.editor.FormPage#getId() + */ + @Override + public String getId() { + return fId; + } + + /** + * Returns the node associated with the current editor input. + * + * @return The node or <code>null</code>. + */ + public Object getEditorInputNode() { + IEditorInput input = getEditorInput(); + return input != null ? input.getAdapter(Object.class) : null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/IEditorPage.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/IEditorPage.java new file mode 100644 index 000000000..21ef97c9c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/IEditorPage.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.interfaces; + +import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.ui.forms.editor.IFormPage; + +/** + * Target Explorer: Details editor page public interface. + */ +public interface IEditorPage extends IFormPage, IExecutableExtension { + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/IRoot.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/IRoot.java new file mode 100644 index 000000000..de53c26af --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/IRoot.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.interfaces; + +import org.eclipse.core.runtime.IAdaptable; + +/** + * Target Explorer root node. + */ +public interface IRoot extends IAdaptable { + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/IUIConstants.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/IUIConstants.java new file mode 100644 index 000000000..e10db0787 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/IUIConstants.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.interfaces; + +/** + * Target Explorer UI constants. + */ +public interface IUIConstants { + + /** + * The target explorer view id. + */ + public static final String ID_EXPLORER = "org.eclipse.tm.te.ui.views.TargetExplorer"; //$NON-NLS-1$ + + /** + * The target explorer editor id. + */ + public static final String ID_EDITOR = "org.eclipse.tm.te.ui.view.Editor"; //$NON-NLS-1$ +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/ImageConsts.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/ImageConsts.java new file mode 100644 index 000000000..aba89ee72 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/interfaces/ImageConsts.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.interfaces; + +/** + * Target Explorer: Image registry constants. + */ +public interface ImageConsts { + /** + * The root directory where to load the images from, relative to + * the bundle directory. + */ + public final static String IMAGE_DIR_ROOT = "icons/"; //$NON-NLS-1$ + + /** + * The directory where to load view related images from, relative to + * the image root directory. + */ + public final static String IMAGE_DIR_EVIEW = "eview16/"; //$NON-NLS-1$ + + /** + * The key to access the Target Explorer editor image. + */ + public static final String IMAGE_EDITOR = "TargetExplorerEditor"; //$NON-NLS-1$ +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/View.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/View.java new file mode 100644 index 000000000..1d2775c40 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/View.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.internal; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.jface.action.GroupMarker; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tm.te.ui.views.interfaces.IRoot; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.navigator.CommonNavigator; + + +/** + * Target Explorer View implementation. + * <p> + * The view is based on the Eclipse Common Navigator framework. + */ +public class View extends CommonNavigator { + private final IRoot fRoot; + + /** + * Target Explorer root node implementation + */ + protected static class Root extends PlatformObject implements IRoot { + /** + * Constructor. + */ + public Root() { + } + } + + /** + * Constructor. + */ + public View() { + fRoot = new Root(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.navigator.CommonNavigator#getInitialInput() + */ + @Override + protected Object getInitialInput() { + return fRoot; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.navigator.CommonNavigator#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + super.createPartControl(parent); + + if (getViewSite() != null && getViewSite().getActionBars() != null) { + IToolBarManager tbManager = getViewSite().getActionBars().getToolBarManager(); + if (tbManager != null) { + tbManager.insertBefore("FRAME_ACTION_GROUP_ID", new GroupMarker("group.new")); //$NON-NLS-1$ //$NON-NLS-2$ + tbManager.appendToGroup("group.new", new Separator("group.connect")); //$NON-NLS-1$ //$NON-NLS-2$ + tbManager.appendToGroup("group.connect", new Separator("group.symbols.rd")); //$NON-NLS-1$ //$NON-NLS-2$ + tbManager.appendToGroup("group.symbols.rd", new GroupMarker("group.symbols")); //$NON-NLS-1$ //$NON-NLS-2$ + tbManager.appendToGroup("group.symbols", new Separator("group.refresh")); //$NON-NLS-1$ //$NON-NLS-2$ + tbManager.appendToGroup("group.refresh", new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); //$NON-NLS-1$ + } + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/editor/Editor.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/editor/Editor.java new file mode 100644 index 000000000..8e646d785 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/editor/Editor.java @@ -0,0 +1,211 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.internal.editor; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.tm.te.ui.views.interfaces.IEditorPage; +import org.eclipse.tm.te.ui.views.internal.extensions.EditorPageBinding; +import org.eclipse.tm.te.ui.views.internal.extensions.EditorPageBindingExtensionPointManager; +import org.eclipse.tm.te.ui.views.internal.extensions.EditorPageExtensionPointManager; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IPersistable; +import org.eclipse.ui.IPersistableEditor; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.XMLMemento; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.IFormPage; + + +/** + * Target Explorer: Details editor. + */ +public class Editor extends FormEditor implements IPersistableEditor { + + // The reference to an memento to restore once the editor got activated + private IMemento fMementoToRestore; + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.editor.FormEditor#addPages() + */ + @Override + protected void addPages() { + // Read extension point and add the contributed pages. + IEditorInput input = getEditorInput(); + // Get all applicable editor page bindings + EditorPageBinding[] bindings = EditorPageBindingExtensionPointManager.getInstance().getApplicableEditorPageBindings(input); + for (EditorPageBinding binding : bindings) { + String pageId = binding.getPageId(); + if (pageId != null) { + // Get the corresponding editor page instance + IEditorPage page = EditorPageExtensionPointManager.getInstance().getEditorPage(pageId, true); + if (page != null) { + try { + // Associate this editor with the page instance. + // This is typically done in the constructor, but we are + // utilizing a default constructor to instantiate the page. + page.initialize(this); + + // Read in the "insertBefore" and "insertAfter" properties of the binding + String insertBefore = binding.getInsertBefore().trim(); + String insertAfter = binding.getInsertAfter().trim(); + + // insertBefore will eclipse insertAfter is both is specified. + if (!"".equals(insertBefore)) { //$NON-NLS-1$ + // If it is "first", we insert the page at index 0 + if ("first".equalsIgnoreCase(insertBefore)) { //$NON-NLS-1$ + addPage(0, page); + } else { + // Find the index of the page we shall insert this page before + int index = getIndexOf(insertBefore); + if (index != -1) addPage(index, page); + else addPage(page); + } + } else if (!"".equals(insertAfter) && !"last".equalsIgnoreCase(insertAfter)) { //$NON-NLS-1$ //$NON-NLS-2$ + // Find the index of the page we shall insert this page after + int index = getIndexOf(insertAfter); + if (index != -1 && index + 1 < pages.size()) addPage(index + 1, page); + else addPage(page); + } else { + // And add the page to the editor as last page. + addPage(page); + } + } catch (PartInitException e) { /* ignored on purpose */ } + } + } + } + + if (fMementoToRestore != null) { + // Loop over all registered pages and pass on the editor specific memento + // to the pages which implements IPersistableEditor as well + for (Object page : pages) { + if (page instanceof IPersistableEditor) { + ((IPersistableEditor)page).restoreState(fMementoToRestore); + } + } + fMementoToRestore = null; + } + } + + /** + * Returns the index of the page with the given id. + * + * @param pageId The page id. Must be not <code>null</code>. + * @return The page index or <code>-1</code> if not found. + */ + private int getIndexOf(String pageId) { + assert pageId != null; + for (int i = 0; i < pages.size(); i++) { + Object page = pages.get(i); + if (page instanceof IFormPage) { + IFormPage fpage = (IFormPage)page; + if (fpage.getId().equals(pageId)) + return i; + } + } + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.editor.FormPage#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput) + */ + @Override + public void init(IEditorSite site, IEditorInput input) throws PartInitException { + super.init(site, input); + + // Update the part name + if (!"".equals(input.getName())) setPartName(input.getName()); //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public void doSave(IProgressMonitor monitor) { + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.EditorPart#doSaveAs() + */ + @Override + public void doSaveAs() { + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed() + */ + @Override + public boolean isSaveAsAllowed() { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IPersistableEditor#restoreState(org.eclipse.ui.IMemento) + */ + public void restoreState(IMemento memento) { + // Get the editor specific memento + fMementoToRestore = internalGetMemento(memento); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento) + */ + public void saveState(IMemento memento) { + // Get the editor specific memento + memento = internalGetMemento(memento); + // Loop over all registered pages and pass on the editor specific memento + // to the pages which implements IPersistable as well + for (Object page : pages) { + if (page instanceof IPersistable) { + ((IPersistable)page).saveState(memento); + } + } + } + + /** + * Internal helper method accessing our editor local child memento + * from the given parent memento. + */ + private IMemento internalGetMemento(IMemento memento) { + // Assume the editor memento to be the same as the parent memento + IMemento editorMemento = memento; + + // If the parent memento is not null, create a child within the parent + if (memento != null) { + editorMemento = memento.getChild(Editor.class.getName()); + if (editorMemento == null) { + editorMemento = memento.createChild(Editor.class.getName()); + } + } else { + // The parent memento is null. Create a new internal instance + // of a XMLMemento. This case is happening if the user switches + // to another perspective an the view becomes visible by this switch. + editorMemento = XMLMemento.createWriteRoot(Editor.class.getName()); + } + + return editorMemento; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.MultiPageEditorPart#getAdapter(java.lang.Class) + */ + @SuppressWarnings("rawtypes") + @Override + public Object getAdapter(Class adapter) { + // We pass on the adapt request to the currently active page + Object adapterInstance = getActivePageInstance() != null ? getActivePageInstance().getAdapter(adapter) : null; + if (adapterInstance == null) { + // If failed to adapt via the currently active page, pass on to the super implementation + adapterInstance = super.getAdapter(adapter); + } + return adapterInstance; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/editor/EditorInput.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/editor/EditorInput.java new file mode 100644 index 000000000..85d37cd77 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/editor/EditorInput.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.internal.editor; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.tm.te.ui.views.activator.UIPlugin; +import org.eclipse.tm.te.ui.views.interfaces.IUIConstants; +import org.eclipse.tm.te.ui.views.interfaces.ImageConsts; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IPersistableElement; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.navigator.CommonNavigator; +import org.eclipse.ui.navigator.CommonViewer; + + +/** + * Target Explorer: Details editor input implementation. + */ +public class EditorInput implements IEditorInput, IPersistableElement { + // The parent editor id + private final String fId; + // The editor input name, once determined + private String fName; + // The node (selection) the editor is showing + private final Object fNode; + + /** + * Constructor. + * + * @param node The node (selection) the editor is showing. Must be not <code>null</code>. + */ + public EditorInput(Object node) { + this(node, IUIConstants.ID_EDITOR); + } + + /** + * Constructor. + * + * @param node The node (selection) the editor is showing. Must be not <code>null</code>. + * @param id The parent editor id or <code>null</code> + */ + public EditorInput(Object node, String id) { + super(); + fId = id; + assert node != null; + fNode = node; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (fNode != null && obj instanceof EditorInput) { + return fNode.equals(((EditorInput)obj).fNode) + && (fId != null ? fId.equals(((EditorInput)obj).fId) : ((EditorInput)obj).fId == null); + } + return super.equals(obj); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return fNode != null ? fNode.hashCode() << 16 + (fId != null ? fId.hashCode() : 0) : super.hashCode(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IEditorInput#exists() + */ + public boolean exists() { + return fNode != null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IEditorInput#getImageDescriptor() + */ + public ImageDescriptor getImageDescriptor() { + return UIPlugin.getImageDescriptor(ImageConsts.IMAGE_EDITOR); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IEditorInput#getName() + */ + public String getName() { + if (fName == null && fNode != null) { + CommonViewer viewer = getViewer(); + fName = viewer != null && viewer.getLabelProvider() instanceof ILabelProvider ? ((ILabelProvider)viewer.getLabelProvider()).getText(fNode) : fNode.toString(); + } + + return fName != null ? fName : ""; //$NON-NLS-1$ + } + + /** + * Get the common viewer used by the Target Explorer view instance. + * + * @return The common viewer or <code>null</code> + */ + protected CommonViewer getViewer() { + if (PlatformUI.getWorkbench() != null && PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null + && PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() != null) { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IViewPart part = page.findView(IUIConstants.ID_EXPLORER); + if (part instanceof CommonNavigator) { + return ((CommonNavigator)part).getCommonViewer(); + } + } + + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IEditorInput#getPersistable() + */ + public IPersistableElement getPersistable() { + // We cannot persist this kind of editor input. + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IPersistableElement#getFactoryId() + */ + public String getFactoryId() { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento) + */ + public void saveState(IMemento memento) { + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IEditorInput#getToolTipText() + */ + public String getToolTipText() { + return getName(); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) + */ + @SuppressWarnings("rawtypes") + public Object getAdapter(Class adapter) { + if (IPersistableElement.class.isAssignableFrom(adapter)) { + return getPersistable(); + } + + // If the adapter can be applied to the node instance, return the node + Object adapted = Platform.getAdapterManager().getAdapter(fNode, adapter); + if (adapted != null) return adapted; + + return Platform.getAdapterManager().getAdapter(this, adapter); + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/expressions/EditorPropertyTester.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/expressions/EditorPropertyTester.java new file mode 100644 index 000000000..4e3897c27 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/expressions/EditorPropertyTester.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.internal.expressions; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.tm.te.ui.views.internal.editor.EditorInput; +import org.eclipse.tm.te.ui.views.internal.extensions.EditorPageBindingExtensionPointManager; +import org.eclipse.ui.IEditorInput; + + +/** + * Target Explorer: Details editor property tester implementation. + */ +public class EditorPropertyTester extends PropertyTester { + + /* (non-Javadoc) + * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object) + */ + public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { + if ("hasApplicableEditorBindings".equals(property)) { //$NON-NLS-1$ + // Create a fake editor input object + IEditorInput input = new EditorInput(receiver); + return expectedValue.equals(Boolean.valueOf(EditorPageBindingExtensionPointManager.getInstance().getApplicableEditorPageBindings(input).length > 0)); + } + return false; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/extensions/EditorPageBinding.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/extensions/EditorPageBinding.java new file mode 100644 index 000000000..059912002 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/extensions/EditorPageBinding.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.internal.extensions; + +import org.eclipse.core.expressions.Expression; +import org.eclipse.core.expressions.ExpressionConverter; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.tm.te.core.extensions.ExecutableExtension; + +/** + * Target Explorer: Details editor page binding implementation. + */ +public class EditorPageBinding extends ExecutableExtension { + private String fPageId; + private String fInsertBefore; + private String fInsertAfter; + private Expression fExpression; + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.views.internal.extensions.ExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object) + */ + @Override + public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { + super.setInitializationData(config, propertyName, data); + + if (config != null) { + // Initialize the page id field by reading the <pageId> extension attribute. + // Throws an exception if the id is empty or null. + fPageId = config.getAttribute("pageId"); //$NON-NLS-1$ + if (fPageId == null || fPageId.trim().length() == 0) { + throw createMissingMandatoryAttributeException("pageId", config.getContributor().getName()); //$NON-NLS-1$ + } + + // Initialize the insertBefore field by reading the <insertBefore> extension attribute if present. + fInsertBefore = config.getAttribute("insertBefore"); //$NON-NLS-1$ + if (fInsertBefore == null || fInsertBefore.trim().length() == 0) fInsertBefore = ""; //$NON-NLS-1$ + + // Initialize the insertAfter field by reading the <insertAfter> extension attribute if present. + fInsertAfter = config.getAttribute("insertAfter"); //$NON-NLS-1$ + if (fInsertAfter == null || fInsertAfter.trim().length() == 0) fInsertAfter = ""; //$NON-NLS-1$ + + IConfigurationElement[] children = config.getChildren(); + if (children != null && children.length > 0) { + // Should only be one - enablement + fExpression = ExpressionConverter.getDefault().perform(children[0]); + } + + } + } + + /** + * Returns the editor page id which is associated with this binding. + * + * @return The editor page id. + */ + public String getPageId() { + return fPageId; + } + + /** + * Returns the enablement expression which is associated with this binding. + * + * @return The enablement expression or <code>null</code>. + */ + public Expression getEnablement() { + return fExpression; + } + + /** + * Returns the "insertBefore" property for this binding. + * + * @return The "insertBefore" property of an empty string. + */ + public String getInsertBefore() { + return fInsertBefore; + } + + /** + * Returns the "insertAfter" property for this binding. + * + * @return The "insertAfter" property of an empty string. + */ + public String getInsertAfter() { + return fInsertAfter; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/extensions/EditorPageBindingExtensionPointManager.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/extensions/EditorPageBindingExtensionPointManager.java new file mode 100644 index 000000000..e1451117f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/extensions/EditorPageBindingExtensionPointManager.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.internal.extensions; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.expressions.EvaluationContext; +import org.eclipse.core.expressions.EvaluationResult; +import org.eclipse.core.expressions.Expression; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.tm.te.core.extensions.AbstractExtensionPointManager; +import org.eclipse.tm.te.core.extensions.ExecutableExtensionProxy; +import org.eclipse.tm.te.ui.views.activator.UIPlugin; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.ISources; + + +/** + * Target Explorer: Details editor page binding extension point manager implementation. + */ +public class EditorPageBindingExtensionPointManager extends AbstractExtensionPointManager<EditorPageBinding> { + + /* + * Thread save singleton instance creation. + */ + private static class LazyInstance { + public static EditorPageBindingExtensionPointManager fInstance = new EditorPageBindingExtensionPointManager(); + } + + /** + * Constructor. + */ + EditorPageBindingExtensionPointManager() { + super(); + } + + /** + * Returns the singleton instance of the extension point manager. + */ + public static EditorPageBindingExtensionPointManager getInstance() { + return LazyInstance.fInstance; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.views.internal.extensions.AbstractExtensionPointManager#getExtensionPointId() + */ + @Override + protected String getExtensionPointId() { + return "org.eclipse.tm.te.ui.views.editorPageBindings"; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.views.internal.extensions.AbstractExtensionPointManager#getConfigurationElementName() + */ + @Override + protected String getConfigurationElementName() { + return "editorPageBinding"; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.views.internal.extensions.AbstractExtensionPointManager#doCreateExtensionProxy(org.eclipse.core.runtime.IConfigurationElement) + */ + @Override + protected ExecutableExtensionProxy<EditorPageBinding> doCreateExtensionProxy(IConfigurationElement element) throws CoreException { + return new ExecutableExtensionProxy<EditorPageBinding>(element) { + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.views.internal.extensions.ExecutableExtensionProxy#newInstance() + */ + @Override + public EditorPageBinding newInstance() { + EditorPageBinding instance = new EditorPageBinding(); + if (instance != null) { + try { + instance.setInitializationData(getConfigurationElement(), null, null); + } catch (CoreException e) { + IStatus status = new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), + e.getLocalizedMessage(), e); + UIPlugin.getDefault().getLog().log(status); + } + } + return instance; + } + }; + } + + /** + * Returns the applicable editor page bindings for the given data source model node.. + * + * @param input The active editor input or <code>null</code>. + * @return The list of applicable editor page bindings or an empty array. + */ + public EditorPageBinding[] getApplicableEditorPageBindings(IEditorInput input) { + List<EditorPageBinding> applicable = new ArrayList<EditorPageBinding>(); + + for (EditorPageBinding binding : getEditorPageBindings()) { + Expression enablement = binding.getEnablement(); + + // The page binding is applicable by default if no expression + // is specified. + boolean isApplicable = enablement == null; + + if (enablement != null && input != null) { + // Extract the node from the editor input + Object node = input.getAdapter(Object.class); + if (node != null) { + // Set the default variable to the data source model node instance. + EvaluationContext context = new EvaluationContext(null, node); + // Set the "activeEditorInput" variable to the data source model node instance. + context.addVariable(ISources.ACTIVE_EDITOR_INPUT_NAME, node); + // Evaluate the expression + try { + isApplicable = enablement.evaluate(context).equals(EvaluationResult.TRUE); + } catch (CoreException e) { + IStatus status = new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), + e.getLocalizedMessage(), e); + UIPlugin.getDefault().getLog().log(status); + } + } else { + // The enablement is false by definition if we cannot + // determine the data source model node. + isApplicable = false; + } + } + + // Add the page if applicable + if (isApplicable) applicable.add(binding); + } + + return applicable.toArray(new EditorPageBinding[applicable.size()]); + } + + /** + * Returns the list of all contributed editor page bindings. + * + * @return The list of contributed editor page bindings, or an empty array. + */ + public EditorPageBinding[] getEditorPageBindings() { + List<EditorPageBinding> contributions = new ArrayList<EditorPageBinding>(); + Collection<ExecutableExtensionProxy<EditorPageBinding>> editorPageBindings = getExtensions().values(); + for (ExecutableExtensionProxy<EditorPageBinding> editorPageBinding : editorPageBindings) { + EditorPageBinding instance = editorPageBinding.getInstance(); + if (instance != null && !contributions.contains(instance)) { + contributions.add(instance); + } + } + + return contributions.toArray(new EditorPageBinding[contributions.size()]); + } + + /** + * Returns the editor page binding identified by its unique id. If no editor + * page binding with the specified id is registered, <code>null</code> is returned. + * + * @param id The unique id of the editor page binding or <code>null</code> + * + * @return The editor page instance or <code>null</code>. + */ + public EditorPageBinding getEditorPageBinding(String id) { + EditorPageBinding contribution = null; + if (getExtensions().containsKey(id)) { + ExecutableExtensionProxy<EditorPageBinding> proxy = getExtensions().get(id); + // Get the extension instance + contribution = proxy.getInstance(); + } + + return contribution; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/extensions/EditorPageExtensionPointManager.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/extensions/EditorPageExtensionPointManager.java new file mode 100644 index 000000000..b36563b01 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/extensions/EditorPageExtensionPointManager.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.internal.extensions; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.tm.te.core.extensions.AbstractExtensionPointManager; +import org.eclipse.tm.te.core.extensions.ExecutableExtensionProxy; +import org.eclipse.tm.te.ui.views.interfaces.IEditorPage; + + +/** + * Target Explorer: Details editor page extension point manager implementation. + */ +public class EditorPageExtensionPointManager extends AbstractExtensionPointManager<IEditorPage> { + /* + * Thread save singleton instance creation. + */ + private static class LazyInstance { + public static EditorPageExtensionPointManager fInstance = new EditorPageExtensionPointManager(); + } + + /** + * Constructor. + */ + EditorPageExtensionPointManager() { + super(); + } + + /** + * Returns the singleton instance of the extension point manager. + */ + public static EditorPageExtensionPointManager getInstance() { + return LazyInstance.fInstance; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.views.internal.extensions.AbstractExtensionPointManager#getExtensionPointId() + */ + @Override + protected String getExtensionPointId() { + return "org.eclipse.tm.te.ui.views.editorPages"; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.views.internal.extensions.AbstractExtensionPointManager#getConfigurationElementName() + */ + @Override + protected String getConfigurationElementName() { + return "editorPage"; //$NON-NLS-1$ + } + + /** + * Returns the list of all contributed editor pages. + * + * @param unique If <code>true</code>, the method returns new instances for each + * contributed editor page. + * + * @return The list of contributed editor pages, or an empty array. + */ + public IEditorPage[] getEditorPages(boolean unique) { + List<IEditorPage> contributions = new ArrayList<IEditorPage>(); + Collection<ExecutableExtensionProxy<IEditorPage>> editorPages = getExtensions().values(); + for (ExecutableExtensionProxy<IEditorPage> editorPage : editorPages) { + IEditorPage instance = unique ? editorPage.newInstance() : editorPage.getInstance(); + if (instance != null && !contributions.contains(instance)) { + contributions.add(instance); + } + } + + return contributions.toArray(new IEditorPage[contributions.size()]); + } + + /** + * Returns the editor page identified by its unique id. If no editor + * page with the specified id is registered, <code>null</code> is returned. + * + * @param id The unique id of the editor page or <code>null</code> + * @param unique If <code>true</code>, the method returns new instances of the editor page contribution. + * + * @return The editor page instance or <code>null</code>. + */ + public IEditorPage getEditorPage(String id, boolean unique) { + IEditorPage contribution = null; + if (getExtensions().containsKey(id)) { + ExecutableExtensionProxy<IEditorPage> proxy = getExtensions().get(id); + // Get the extension instance + contribution = unique ? proxy.newInstance() : proxy.getInstance(); + } + + return contribution; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/nls/Messages.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/nls/Messages.java new file mode 100644 index 000000000..5a0520bb9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/nls/Messages.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.internal.nls; + +import org.eclipse.osgi.util.NLS; + +/** + * Target Explorer UI plugin externalized strings management. + */ +public class Messages extends NLS { + + // The plug-in resource bundle name + private static final String BUNDLE_NAME = "org.eclipse.tm.te.ui.views.internal.nls.Messages"; //$NON-NLS-1$ + + /** + * Static constructor. + */ + static { + // Load message values from bundle file + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + // **** Declare externalized string id's down here ***** + + public static String PropertiesCommandHandler_error_initPartFailed; +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/nls/Messages.properties new file mode 100644 index 000000000..c88578ab4 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/nls/Messages.properties @@ -0,0 +1,6 @@ +# +# org.eclipse.tm.te.ui.views +# Externalized Strings. +# + +PropertiesCommandHandler_error_initPartFailed=Failed to initialize the Target Explorer details editor. diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/targets/handler/PropertiesCommandHandler.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/targets/handler/PropertiesCommandHandler.java new file mode 100644 index 000000000..ae76a2a03 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/internal/targets/handler/PropertiesCommandHandler.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.internal.targets.handler; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tm.te.ui.views.activator.UIPlugin; +import org.eclipse.tm.te.ui.views.interfaces.IUIConstants; +import org.eclipse.tm.te.ui.views.internal.editor.EditorInput; +import org.eclipse.tm.te.ui.views.internal.nls.Messages; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; + + +/** + * Target Explorer: Properties command handler implementation. + */ +public class PropertiesCommandHandler extends AbstractHandler { + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + public Object execute(ExecutionEvent event) throws ExecutionException { + // Get the active selection + ISelection selection = HandlerUtil.getCurrentSelection(event); + if (selection instanceof IStructuredSelection && !selection.isEmpty()) { + Object element = ((IStructuredSelection)selection).getFirstElement(); + if (element != null) { + // Get the currently active workbench window + IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event); + if (window == null) window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window != null) { + // Get the active page + IWorkbenchPage page = window.getActivePage(); + // Create the editor input object + IEditorInput input = new EditorInput(element); + // Check for the Target Explorer editor already opened + IEditorReference[] references = page.findEditors(input, IUIConstants.ID_EDITOR, IWorkbenchPage.MATCH_INPUT); + if (references.length == 0) { + try { + // Opens the Target Explorer properties editor + page.openEditor(input, IUIConstants.ID_EDITOR); + } catch (PartInitException e) { + IStatus status = new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), + Messages.PropertiesCommandHandler_error_initPartFailed, e); + UIPlugin.getDefault().getLog().log(status); + } + } + } + } + } + + return null; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/perspective/PerspectiveFactory.java b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/perspective/PerspectiveFactory.java new file mode 100644 index 000000000..8af6ac492 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui.views/src/org/eclipse/tm/te/ui/views/perspective/PerspectiveFactory.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.views.perspective; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.ui.IFolderLayout; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; +import org.eclipse.ui.IPlaceholderFolderLayout; +import org.eclipse.ui.PlatformUI; + +/** + * Target Explorer: Perspective factory. + */ +public class PerspectiveFactory extends PlatformObject implements IPerspectiveFactory { + private final static String[] VIEWS_FOR_LEFT_AREA = new String[] { + "org.eclipse.tm.te.ui.views.TargetExplorer", //$NON-NLS-1$ + "org.eclipse.ui.navigator.ProjectExplorer" //$NON-NLS-1$ + }; + + /* (non-Javadoc) + * @see org.eclipse.ui.IPerspectiveFactory#createInitialLayout(org.eclipse.ui.IPageLayout) + */ + public void createInitialLayout(IPageLayout layout) { + // editor is placed for free + String editorArea = layout.getEditorArea(); + + boolean leftAreaActive = false; + for (String viewId : VIEWS_FOR_LEFT_AREA) { + leftAreaActive |= PlatformUI.getWorkbench().getViewRegistry().find(viewId) != null; + if (leftAreaActive) break; + } + + if (leftAreaActive) { + // place resource navigator to the left of editor area + IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, 0.3f, editorArea); //$NON-NLS-1$ + + for (String viewId : VIEWS_FOR_LEFT_AREA) { + if (PlatformUI.getWorkbench().getViewRegistry().find(viewId) != null) { + left.addView(viewId); + } + } + } else { + layout.createPlaceholderFolder("left", IPageLayout.LEFT, 0.3f, editorArea); //$NON-NLS-1$ + } + + // place console below the main editor + IFolderLayout lowerRight = layout.createFolder("lowerRight", IPageLayout.BOTTOM, 0.7f, editorArea); //$NON-NLS-1$ + if (PlatformUI.getWorkbench().getViewRegistry().find("org.eclipse.pde.runtime.LogView") != null) //$NON-NLS-1$ + lowerRight.addView("org.eclipse.pde.runtime.LogView"); //$NON-NLS-1$ + if (PlatformUI.getWorkbench().getViewRegistry().find("org.eclipse.ui.views.TaskList") != null) //$NON-NLS-1$ + lowerRight.addPlaceholder("org.eclipse.ui.views.TaskList"); //$NON-NLS-1$ + + // place details view port to the right of editor area + IPlaceholderFolderLayout right = layout.createPlaceholderFolder("right", IPageLayout.RIGHT, 0.75f, editorArea); //$NON-NLS-1$ + if (PlatformUI.getWorkbench().getViewRegistry().find(IPageLayout.ID_OUTLINE) != null) + right.addPlaceholder(IPageLayout.ID_OUTLINE); + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/.classpath b/target_explorer/plugins/org.eclipse.tm.te.ui/.classpath new file mode 100644 index 000000000..64c5e31b7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/.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/J2SE-1.5"/> + <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.tm.te.ui/.project b/target_explorer/plugins/org.eclipse.tm.te.ui/.project new file mode 100644 index 000000000..3ce2b5292 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.tm.te.ui</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/.settings/org.eclipse.jdt.core.prefs b/target_explorer/plugins/org.eclipse.tm.te.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..441efa153 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,77 @@ +#Thu Aug 19 09:20:49 CEST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +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.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=ignore +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=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +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.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.5 diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tm.te.ui/META-INF/MANIFEST.MF new file mode 100644 index 000000000..371798215 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/META-INF/MANIFEST.MF @@ -0,0 +1,24 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.tm.te.ui;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.tm.te.ui.activator.UIPlugin +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0", + org.eclipse.core.expressions;bundle-version="3.4.200", + org.eclipse.ui;bundle-version="3.6.2", + org.eclipse.ui.forms;bundle-version="3.5.2" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Export-Package: org.eclipse.tm.te.ui;version="1.0.0", + org.eclipse.tm.te.ui.dialogs;version="1.0.0", + org.eclipse.tm.te.ui.forms;version="1.0.0", + org.eclipse.tm.te.ui.images;version="1.0.0", + org.eclipse.tm.te.ui.interfaces;version="1.0.0", + org.eclipse.tm.te.ui.nls;version="1.0.0", + org.eclipse.tm.te.ui.nodes;version="1.0.0", + org.eclipse.tm.te.ui.tables;version="1.0.0", + org.eclipse.tm.te.ui.tables.properties;version="1.0.0", + org.eclipse.tm.te.ui.trees;version="1.0.0" diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/build.properties b/target_explorer/plugins/org.eclipse.tm.te.ui/build.properties new file mode 100644 index 000000000..aa1a00826 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.properties diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/plugin.properties b/target_explorer/plugins/org.eclipse.tm.te.ui/plugin.properties new file mode 100644 index 000000000..9007e2197 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/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: +# Uwe Stieber (Wind River) - initial API and implementation +################################################################################## + +pluginName = Target Explorer, Common UI Controls and Helper +providerName = Eclipse.org diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/AbstractViewerComparator.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/AbstractViewerComparator.java new file mode 100644 index 000000000..4d4e1e9fe --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/AbstractViewerComparator.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui; + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; + +/** + * Target Explorer: Common viewer comparator implementation. + */ +public abstract class AbstractViewerComparator extends ViewerComparator { + // Reference to the viewer + private final Viewer fViewer; + + /** + * Constructor. + * + * @param viewer The parent viewer. Must be not <code>null</code>. + */ + public AbstractViewerComparator(Viewer viewer) { + assert viewer != null; + fViewer = viewer; + } + + /** + * Returns the parent viewer instance. + * + * @return The parent viewer instance. + */ + protected final Viewer getParentViewer() { + return fViewer; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) { + return doCompare(e1, e2, doGetSortColumnLabel(viewer), doGetSortColumnIndex(viewer) , doDetermineInverter(viewer)); + } + return super.compare(viewer, e1, e2); + } + + /* (non-Javadoc) + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + public int compare(Object o1, Object o2) { + return doCompare(o1, o2, null, -1, doDetermineInverter(getParentViewer())); + } + + /** + * Compare the given nodes by the given sort column and inverter. + * + * @param node1 The first node or <code>null</code>. + * @param node2 The second node or <code>null</code>. + * @param sortColumn The sort column text or <code>null</code>. + * @param index The sort column index or <code>-1</code>. + * @param inverter The inverter. + * + * @return The compare result. + */ + protected abstract int doCompare(Object node1, Object node2, String sortColumn, int index, int inverter); + + /** + * Returns the text to compare for the given node and column index. + * + * @param node The node or <code>null</code>. + * @param index The column index or <code>-1</code>. + * + * @return The text for the given node and column index or <code>null</code>. + */ + protected abstract String doGetText(Object node, int index); + + /** + * Determine if or if not the sort direction needs to be inverted. + * + * @param viewer The viewer or <code>null</code>. + * @return <code>1</code> for original sort order, or <code>-1</code> for inverted sort order. + */ + protected abstract int doDetermineInverter(Viewer viewer); + + /** + * Return the label of the sort column of the given viewer. + * + * @param viewer The viewer or <code>null</code>. + * @return The label of the sort column or an empty string. + */ + protected abstract String doGetSortColumnLabel(Viewer viewer); + + /** + * Return the index of the sort column of the given viewer. + * + * @param viewer The viewer or <code>null</code>. + * @return The index of the sort column or <code>-1</code>. + */ + protected abstract int doGetSortColumnIndex(Viewer viewer); +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/WorkbenchPartControl.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/WorkbenchPartControl.java new file mode 100644 index 000000000..6dab3be48 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/WorkbenchPartControl.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tm.te.ui.activator.UIPlugin; +import org.eclipse.tm.te.ui.forms.CustomFormToolkit; +import org.eclipse.ui.ISelectionService; +import org.eclipse.ui.IWorkbenchPart; + + +/** + * Target Explorer: Common workbench part control implementation. + */ +public class WorkbenchPartControl extends PlatformObject { + /** + * Reference to the parent workbench part the control might be embedded in. + */ + private final IWorkbenchPart fParentPart; + + /** + * Reference to the form toolkit instance provided via {@link #setupFormPanel(Composite, CustomFormToolkit)}. + */ + private CustomFormToolkit fFormToolkit = null; + + /** + * Reference to the parent control. + */ + private Composite fParentControl; + + /** + * Constructor. + */ + public WorkbenchPartControl() { + this(null); + } + + /** + * Constructor. + * + * @param parentPart The parent workbench part this control is embedded in or <code>null</code>. + */ + public WorkbenchPartControl(IWorkbenchPart parentPart) { + super(); + fParentPart = parentPart; + } + + /** + * Returns the parent workbench part the control might be embedded in. + * + * @return The parent workbench part or <code>null</code>. + */ + public final IWorkbenchPart getParentPart() { + return fParentPart; + } + + /** + * Returns if the <code>setupPanel(...)</code> method has been called at least once with + * a non-null parent control. + * + * @return <code>true</code> if the associated parent control is not <code>null</code>, <code>false</code> otherwise. + */ + public final boolean isControlCreated() { + return (fParentControl != null); + } + + /** + * Returns the parent control of the control. + * + * @return The parent control or <code>null</code>. + */ + public final Composite getParentControl() { + return fParentControl; + } + + /** + * Cleanup all resources the control might have been created. + */ + public void dispose() { + fParentControl = null; + } + + /** + * Creates the controls UI elements. + * + * @param parent The parent composite. Must not be <code>null</code>. + * @param toolkit The {@link CustomFormToolkit} instance. Must be not <code>null</code>. + */ + public void setupFormPanel(Composite parent, CustomFormToolkit toolkit) { + assert parent != null && toolkit != null; + fParentControl = parent; + fFormToolkit = toolkit; + } + + /** + * Returns the associated form toolkit instance. + * + * @return The form toolkit instance or <code>null</code> if not initialized yet. + */ + protected final CustomFormToolkit getFormToolkit() { + return fFormToolkit; + } + + /** + * Returns the selection service of the workbench. + * + * @return The selection service or <code>null</code>. + */ + protected final ISelectionService getSelectionService() { + ISelectionService selectionService = null; + // Check if plugin, workbench and active workbench window are still valid + if (UIPlugin.getDefault() != null && UIPlugin.getDefault().getWorkbench() != null + && UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow() != null) { + selectionService = UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getSelectionService(); + } + return selectionService; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/activator/UIPlugin.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/activator/UIPlugin.java new file mode 100644 index 000000000..d8d6e1e1b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/activator/UIPlugin.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.activator; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class UIPlugin extends AbstractUIPlugin { + // The shared instance + private static UIPlugin plugin; + + /** + * The constructor + */ + public UIPlugin() { + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static UIPlugin 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; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#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.tm.te.ui/src/org/eclipse/tm/te/ui/dialogs/CustomTrayDialog.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/dialogs/CustomTrayDialog.java new file mode 100644 index 000000000..702bab109 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/dialogs/CustomTrayDialog.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.dialogs; + +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.dialogs.TrayDialog; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.te.ui.activator.UIPlugin; +import org.eclipse.ui.PlatformUI; + + +/** + * Target Explorer: Custom tray dialog implementation. + */ +public class CustomTrayDialog extends TrayDialog { + private String fContextHelpId = null; + + // the dialog storage + private IDialogSettings fDialogSettings; + + /** + * Constructor. + * + * @param shell The parent shell or <code>null</code>. + */ + public CustomTrayDialog(Shell shell) { + this(shell, null); + } + + /** + * Constructor. + * + * @param shell The parent shell or <code>null</code>. + * @param contextHelpId The dialog context help id or <code>null</code>. + */ + public CustomTrayDialog(Shell shell, String contextHelpId) { + super(shell); + initializeDialogSettings(); + setContextHelpId(contextHelpId); + } + + /** + * Configure the dialogs context help id. + * + * @param contextHelpId The context help id or <code>null</code>. + */ + protected void setContextHelpId(String contextHelpId) { + fContextHelpId = contextHelpId; + setHelpAvailable(fContextHelpId != null); + } + + /** + * Initialize the dialog settings storage. + */ + protected void initializeDialogSettings() { + IDialogSettings settings = doGetDialogSettingsToInitialize(); + assert settings != null; + IDialogSettings section = settings.getSection(getDialogSettingsSectionName()); + if (section == null) { + section = settings.addNewSection(getDialogSettingsSectionName()); + } + setDialogSettings(section); + } + + /** + * Returns the dialog settings container to use and to initialize. This + * method is called from <code>initializeDialogSettings</code> and allows + * overriding the dialog settings container without changing the dialog + * settings structure. + * + * @return The dialog settings container to use. Must be not <code>null</code>. + */ + protected IDialogSettings doGetDialogSettingsToInitialize() { + return UIPlugin.getDefault().getDialogSettings(); + } + + /** + * Returns the section name to use for separating different persistent + * dialog settings from different dialogs. + * + * @return The section name used to store the persistent dialog settings within the plugins persistent + * dialog settings store. + */ + public String getDialogSettingsSectionName() { + return "CustomTrayDialog"; //$NON-NLS-1$ + } + + /** + * Returns the associated dialog settings storage. + * + * @return The dialog settings storage. + */ + public IDialogSettings getDialogSettings() { + // The dialog settings may not been initialized here. Initialize first in this case + // to be sure that we do have always the correct dialog settings. + if (fDialogSettings == null) { + initializeDialogSettings(); + } + return fDialogSettings; + } + + /** + * Sets the associated dialog settings storage. + * + * @return The dialog settings storage. + */ + public void setDialogSettings(IDialogSettings dialogSettings) { + fDialogSettings = dialogSettings; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createDialogArea(Composite parent) { + if (fContextHelpId != null) { + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, fContextHelpId); + } + + // Let the super implementation create the dialog area control + Control control = super.createDialogArea(parent); + // But fix the layout data for the top control + if (control instanceof Composite) { + configureDialogAreaControl((Composite)control); + } + + return control; + } + + /** + * Configure the dialog top control. + * + * @param composite The dialog top control. Must be not <code>null</code>. + */ + protected void configureDialogAreaControl(Composite composite) { + assert composite != null; + Layout layout = composite.getLayout(); + if (layout == null || layout instanceof GridLayout) { + composite.setLayout(new GridLayout()); + } + } + + /** + * Cleanup when dialog is closed. + */ + protected void dispose() { + fDialogSettings = null; + } + + /** + * Cleanup the Dialog and close it. + */ + @Override + public boolean close() { + dispose(); + return super.close(); + } + + /** + * Sets the title for this dialog. + * + * @param title The title. + */ + public void setDialogTitle(String title) { + if (getShell() != null && !getShell().isDisposed()) { + getShell().setText(title); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/forms/CustomFormToolkit.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/forms/CustomFormToolkit.java new file mode 100644 index 000000000..5cb96b578 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/forms/CustomFormToolkit.java @@ -0,0 +1,393 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.forms; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.forms.events.ExpansionEvent; +import org.eclipse.ui.forms.events.IExpansionListener; +import org.eclipse.ui.forms.widgets.ExpandableComposite; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.forms.widgets.Section; + +/** + * Target Explorer: Custom form toolkit for using form elements within + * dialog and wizard pages, or other containers. + */ +public class CustomFormToolkit extends PlatformObject { + // The reference of the wrapped toolkit + private final FormToolkit fToolkit; + + /** + * Constructor. + * + * @param toolkit The {@link FormToolkit} instance to wrap. Must not be <code>null</code>. + */ + public CustomFormToolkit(FormToolkit toolkit) { + super(); + assert toolkit != null; + fToolkit = toolkit; + } + + /** + * Returns the wrapped {@link FormToolkit} instance. + * + * @return The wrapped {@link FormToolkit} instance. + */ + public final FormToolkit getFormToolkit() { + return fToolkit; + } + + /** + * Dispose the form toolkit wrapper. + */ + public void dispose() { + fToolkit.dispose(); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class) + */ + @Override + @SuppressWarnings("rawtypes") + public Object getAdapter(Class adapter) { + if (FormToolkit.class.isAssignableFrom(adapter)) + return getFormToolkit(); + + return super.getAdapter(adapter); + } + + /** + * Returns the number of pixels corresponding to the height of the given + * number of characters. + * <p> + * This methods uses the static {@link Dialog#convertHeightInCharsToPixels(org.eclipse.swt.graphics.FontMetrics, int)} + * method for calculation. + * <p> + * @param chars The number of characters + * @return The corresponding height in pixels + */ + protected int convertHeightInCharsToPixels(Control control, int chars) { + int height = 0; + if (control != null && !control.isDisposed()) { + GC gc = new GC(control); + gc.setFont(JFaceResources.getDialogFont()); + height = Dialog.convertHeightInCharsToPixels(gc.getFontMetrics(), chars); + gc.dispose(); + } + + return height; + } + + /** + * Creates a new scrollable form container within the given parent. If + * <code>overwriteBackground</code> is set, the parent background color + * and background image is applied to the created scrollable form. + * + * @param parent The parent composite. Must not be <code>null</code>. + * @param title The form title or <code>null</code> if none. + * @param overwriteBackground If <code>true</code>, the parent background color and image are applied to the scrollable form. + * + * @return The scrollable form instance. + */ + public ScrolledForm createScrolledForm(Composite parent, String title, boolean overwriteBackground) { + assert parent != null; + + // Create the scrolled form which is the scrollable container for the expandable composite + final ScrolledForm scrollableForm = getFormToolkit().createScrolledForm(parent); + + // Overwrite background color and image if requested + if (overwriteBackground) { + scrollableForm.setBackground(parent.getBackground()); + scrollableForm.setBackgroundImage(parent.getBackgroundImage()); + } + + // If a title is given, set and decorate the header + if (title != null && scrollableForm.getForm() != null) { + scrollableForm.getForm().setText(title); + getFormToolkit().decorateFormHeading(scrollableForm.getForm()); + } + + return scrollableForm; + } + + /** + * Creates an expandable composite within the given parent scrollable form using the given title. + * If <code>overwriteBackground</code> is set, the parent background color and background image + * is applied to the created expandable composite. + * + * @param scrolledForm The parent scrolled form. Must not be <code>null</code>. + * @param title The expandable composite title. Must not be <code>null</code>. + * @param entriesToShow The number of entries to show within the expanded area. Must be greater than 0. + * @param expanded The initial expanded state of the expandable composite. + * @param overwriteBackground If <code>true</code>, the parent background color and image are applied to the expandable composite. + * + * @return The expandable composite. + */ + public final ExpandableComposite createExpandableComposite(final ScrolledForm scrolledForm, + String title, final int entriesToShow, + boolean expanded, boolean overwriteBackground) { + assert scrolledForm != null && title != null && entriesToShow > 0; + + // Create the expandable composite within the scrollable container + final ExpandableComposite expandable = getFormToolkit().createExpandableComposite(scrolledForm.getBody(), ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT); + expandable.setText(title); + + // Overwrite background color and image if requested + if (overwriteBackground) { + expandable.setBackground(scrolledForm.getBackground()); + expandable.setBackgroundImage(scrolledForm.getBackgroundImage()); + } + + expandable.setLayout(new GridLayout()); + expandable.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // Create an associate an expansion listener to the expandable form + expandable.addExpansionListener(new IExpansionListener() { + boolean notExpanded = true; + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.events.IExpansionListener#expansionStateChanged(org.eclipse.ui.forms.events.ExpansionEvent) + */ + public void expansionStateChanged(ExpansionEvent e) { + // Always set the scrolled form to re-flow. Otherwise it wouldn't + // re-arrange the controls following this expandable composite on + // collapse. + scrolledForm.reflow(true); + + // Get the shell from the scrolled form. + Shell shell = scrolledForm.getShell(); + if (shell != null && !shell.isDisposed() && e.getState() && notExpanded) { + // And recalculate the bounds on expand + shell.setRedraw(false); + Rectangle shellBounds = shell.getBounds(); + + // Assume at minimum 4 controls within the expandable area. + shellBounds.height += convertHeightInCharsToPixels(expandable, Math.max(4, entriesToShow)) + IDialogConstants.VERTICAL_SPACING; + + shell.setBounds(shellBounds); + shell.setRedraw(true); + notExpanded = false; + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.events.IExpansionListener#expansionStateChanging(org.eclipse.ui.forms.events.ExpansionEvent) + */ + public void expansionStateChanging(ExpansionEvent e) { + } + }); + + // Create the client area the caller can use as parent for the control + Composite client = getFormToolkit().createComposite(expandable); + client.setLayout(new GridLayout()); + + // Overwrite background color and image if requested + if (overwriteBackground) { + client.setBackground(scrolledForm.getBackground()); + client.setBackgroundImage(scrolledForm.getBackgroundImage()); + } + + // Set the initial expansion state + expandable.setExpanded(expanded); + // And associated the client + expandable.setClient(client); + + return expandable; + } + + /** + * Creates an expandable section within the given parent scrollable form using the given title. + * If <code>overwriteBackground</code> is set, the parent background color and background image + * is applied to the created section. + * + * @param parent The parent scrolled form. Must not be <code>null</code>. + * @param title The expandable composite title. Must not be <code>null</code>. + * @param entriesToShow The number of entries to show within the expanded area. Must be greater than 0. + * @param expanded The initial expanded state of the section. + * @param overwriteBackground If <code>true</code>, the parent background color and image are applied to the section. + * + * @return The section. + */ + public final Section createSection(final ScrolledForm scrolledForm, + String title, final int entriesToShow, + boolean expanded, boolean overwriteBackground) { + assert scrolledForm != null && title != null && entriesToShow > 0; + + // Create the section within the scrollable container + final Section section = getFormToolkit().createSection(scrolledForm.getBody(), ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT); + section.setText(title); + + // Overwrite background color and image if requested + if (overwriteBackground) { + section.setBackground(scrolledForm.getBackground()); + section.setBackgroundImage(scrolledForm.getBackgroundImage()); + } + + section.setLayout(new GridLayout()); + section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // Create an associate an expansion listener to the expandable form + section.addExpansionListener(new IExpansionListener() { + boolean notExpanded = true; + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.events.IExpansionListener#expansionStateChanged(org.eclipse.ui.forms.events.ExpansionEvent) + */ + public void expansionStateChanged(ExpansionEvent e) { + // Always set the scrolled form to re-flow. Otherwise it wouldn't + // re-arrange the controls following this expandable composite on + // collapse. + scrolledForm.reflow(true); + + // Get the shell from the scrolled form. + Shell shell = scrolledForm.getShell(); + if (shell != null && !shell.isDisposed() && e.getState() && notExpanded) { + // And recalculate the bounds on expand + shell.setRedraw(false); + Rectangle shellBounds = shell.getBounds(); + + // Assume at minimum 4 controls within the expandable area. + shellBounds.height += convertHeightInCharsToPixels(section, Math.max(4, entriesToShow)) + IDialogConstants.VERTICAL_SPACING; + + shell.setBounds(shellBounds); + shell.setRedraw(true); + notExpanded = false; + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.forms.events.IExpansionListener#expansionStateChanging(org.eclipse.ui.forms.events.ExpansionEvent) + */ + public void expansionStateChanging(ExpansionEvent e) { + } + }); + + // Create the client area the caller can use as parent for the control + Composite client = getFormToolkit().createComposite(section); + client.setLayout(new GridLayout()); + + // Overwrite background color and image if requested + if (overwriteBackground) { + client.setBackground(scrolledForm.getBackground()); + client.setBackgroundImage(scrolledForm.getBackgroundImage()); + } + + // Set the initial expansion state + section.setExpanded(expanded); + // And associated the client + section.setClient(client); + + return section; + } + + /** + * Creates an non-expandable section within the given parent scrollable form using the given title. + * If <code>overwriteBackground</code> is set, the parent background color and background image + * is applied to the created section. + * + * @param parent The parent scrolled form. Must not be <code>null</code>. + * @param title The expandable composite title. Must not be <code>null</code>. + * @param overwriteBackground If <code>true</code>, the parent background color and image are applied to the section. + * + * @return The section. + */ + public final Section createSection(final ScrolledForm scrolledForm, String title, boolean overwriteBackground) { + assert scrolledForm != null && title != null; + + // Create the section within the scrollable container + final Section section = getFormToolkit().createSection(scrolledForm.getBody(), ExpandableComposite.TITLE_BAR | ExpandableComposite.CLIENT_INDENT); + section.setText(title); + + // Overwrite background color and image if requested + if (overwriteBackground) { + section.setBackground(scrolledForm.getBackground()); + section.setBackgroundImage(scrolledForm.getBackgroundImage()); + } + + // Configure the layout + section.setLayout(new GridLayout()); + section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // Create the client area the caller can use as parent for the control + Composite client = getFormToolkit().createComposite(section); + client.setLayout(new GridLayout()); + + // Overwrite background color and image if requested + if (overwriteBackground) { + client.setBackground(section.getBackground()); + client.setBackgroundImage(section.getBackgroundImage()); + } + + // And associated the client + section.setClient(client); + + return section; + } + + /** + * Creates a composite with a highlighted note entry and a message text. + * This is designed to take up the full width of the page. + * + * @param parent The parent composite. Must not be <code>null</code>. + * @param title The note title. Must not be <code>null</code>. + * @param message The note message Must not be <code>null</code>. + * @param widthHint The note message width hint in pixel or <code>SWT.DEFAULT</code>. + * @param overwriteBackground If <code>true</code>, the parent background color and image are applied to the note composite. + * + * @return The note composite. + */ + public final Composite createNoteComposite(Composite parent, String title, String message, int widthHint, boolean overwriteBackground) { + assert parent != null && title != null && message != null; + + Composite composite = getFormToolkit().createComposite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + layout.marginHeight = 0; layout.marginWidth = 0; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + composite.setFont(parent.getFont()); + + Label noteLabel = getFormToolkit().createLabel(composite, title, SWT.BOLD); + noteLabel.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT)); + noteLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); + + Label messageLabel = getFormToolkit().createLabel(composite, message); + GridData layoutData = new GridData(GridData.FILL_HORIZONTAL); + layoutData.widthHint = widthHint; + messageLabel.setLayoutData(layoutData); + messageLabel.setFont(parent.getFont()); + + // Overwrite background color and image if requested + if (overwriteBackground) { + composite.setBackground(parent.getBackground()); + composite.setBackgroundImage(parent.getBackgroundImage()); + + noteLabel.setBackground(parent.getBackground()); + noteLabel.setBackgroundImage(parent.getBackgroundImage()); + + messageLabel.setBackground(parent.getBackground()); + messageLabel.setBackgroundImage(parent.getBackgroundImage()); + } + + return composite; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageDescriptor.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageDescriptor.java new file mode 100644 index 000000000..626617b0a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageDescriptor.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.images; + +import org.eclipse.jface.resource.CompositeImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Point; + +/** + * Target Explorer: Image descriptor for creating overlays. + */ +public abstract class AbstractImageDescriptor extends CompositeImageDescriptor { + + private String fKey; + private ImageRegistry fRegistry; + + public AbstractImageDescriptor(ImageRegistry reg) { + fRegistry = reg; + } + + protected void setKey(String key) { + fKey = key; + } + + public String getKey() { + return fKey; + } + + protected ImageRegistry getRegistry() { + return fRegistry; + } + + protected void drawCentered(String key, int width, int height) { + drawCentered(fRegistry.get(key), width, height); + } + + protected void drawCentered(Image image, int width, int height) { + if (image != null) { + ImageData imageData = image.getImageData(); + if (imageData != null) { + int x = StrictMath.max(0, (width - imageData.width + 1) / 2); + int y = StrictMath.max(0, (height - imageData.height + 1) / 2); + drawImage(imageData, x, y); + } + } + } + + protected void drawCenterRight(String key, int width, int height) { + Image baseImage = fRegistry.get(key); + if (baseImage != null) { + ImageData imageData = baseImage.getImageData(); + if (imageData != null) { + int x = StrictMath.max(0, width - imageData.width); + int y = StrictMath.max(0, (height - imageData.height + 1) / 2); + drawImage(imageData, x, y); + } + } + } + + protected void drawTopLeft(String key) { + Image baseImage = fRegistry.get(key); + if (baseImage != null) { + ImageData imageData = baseImage.getImageData(); + if (imageData != null) { + drawImage(imageData, 0, 0); + } + } + } + + protected void drawTopRight(String key, int width, int height) { + Image baseImage = fRegistry.get(key); + if (baseImage != null) { + ImageData imageData = baseImage.getImageData(); + if (imageData != null) { + int x = StrictMath.max(0, width - imageData.width); + drawImage(imageData, x, 0); + } + } + } + + protected void drawBottomCenter(String key, int width, int height) { + Image image = fRegistry.get(key); + if (image != null) { + ImageData imageData = image.getImageData(); + if (imageData != null) { + int x = StrictMath.max(0, (width - imageData.width + 1) / 2); + int y = StrictMath.max(0, height - imageData.height); + drawImage(imageData, x, y); + } + } + } + + protected void drawBottomLeft(String key) { + if (getSize() != null) { + Point size = getSize(); + drawBottomLeft(key, size.x, size.y); + } else { + // the default eclipse style guide recommendation is 16x16 + drawBottomLeft(key, 16, 16); + } + } + + protected void drawBottomLeft(String key, int width, int height) { + Image image = fRegistry.get(key); + if (image != null) { + ImageData imageData = image.getImageData(); + if (imageData != null) { + int y = StrictMath.max(0, height - imageData.height); + drawImage(imageData, 0, y); + } + } + } + + protected void drawCenterLeft(String key, int width, int height) { + Image image = fRegistry.get(key); + if (image != null) { + ImageData imageData = image.getImageData(); + if (imageData != null) { + int y = StrictMath.max(0, (height - imageData.height) / 2); + drawImage(imageData, 0, y); + } + } + } + + protected void drawBottomRight(String key) { + if (getSize() != null) { + Point size = getSize(); + drawBottomRight(key, size.x, size.y); + } else { + // the default eclipse style guide recommendation is 16x16 + drawBottomRight(key, 16, 16); + } + } + + protected void drawBottomRight(String key, int width, int height) { + Image image = fRegistry.get(key); + if (image != null) { + ImageData imageData = image.getImageData(); + if (imageData != null) { + int x = StrictMath.max(0, width - imageData.width); + int y = StrictMath.max(0, height - imageData.height); + drawImage(imageData, x, y); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.resource.CompositeImageDescriptor#getTransparentPixel() + */ + @Override + protected int getTransparentPixel() { + Image baseImage = getBaseImage(); + if (baseImage != null && baseImage.getImageData() != null) { + return baseImage.getImageData().transparentPixel; + } + return super.getTransparentPixel(); + } + + /** + * Returns the base image used for the combined image description. This + * method is called from <code>getTransparentPixel()</code> to query the + * transparent color of the palette. + * + * @return The base image or <code>null</code> if none. + */ + protected abstract Image getBaseImage(); +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageRegistry.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageRegistry.java new file mode 100644 index 000000000..849b7d875 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageRegistry.java @@ -0,0 +1,218 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.images; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm.te.ui.activator.UIPlugin; +import org.eclipse.tm.te.ui.nls.Messages; +import org.osgi.framework.Bundle; + + + +/** + * Target Explorer: Abstract image registry that allows for defining fallback paths for images. + */ +public abstract class AbstractImageRegistry extends ImageRegistry { + private List<ImageRegistry> fDelegates = new ArrayList<ImageRegistry>(); + private Map<String,String> fPlugins = new HashMap<String,String>(); + private Map<String,String[]> fLocations = new HashMap<String,String[]>(); + private URL fBaseUrl; + + protected AbstractImageRegistry(Plugin plugin) { + fBaseUrl = plugin.getBundle().getEntry("/"); //$NON-NLS-1$ + } + + /** + * Adds the given image registry as delegate. Delegates are queried if + * an image or image descriptor cannot be found locally. If the image + * registry delegate had been added before, the method will do nothing. + * + * @param registry The image registry. Must be not <code>null</code>. + */ + protected final void addImageRegistryDelegate(ImageRegistry registry) { + assert registry != null; + if (!fDelegates.contains(registry)) fDelegates.add(registry); + } + + /** + * Removes the given image registry from the list of delegates. + * + * @param registry The image registry. Must be not <code>null</code>. + */ + protected final void removeImageRegistryDelegate(ImageRegistry registry) { + assert registry != null; + fDelegates.remove(registry); + } + + /** + * Defines the key for a local image, that must be found below the icons directory + * in the plugin. + * @param key Key by which the image can be referred by. + * @param dir Directory relative to icons/ + * @param name The name of the file defining the icon. The name will be used as + * key. + */ + protected void localImage(String key, String dir, String name) { + if (dir== null || dir.equals(""))//$NON-NLS-1$ + fLocations.put(key, new String[] {"icons/" + name}); //$NON-NLS-1$ + else + fLocations.put(key, new String[] {"icons/" + dir + "/" + name}); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Defines the key for a non-local image, that must be found below the icons directory + * of some plugin. + * @param key Key by which the image can be referred by. + * @param plugin The plugin id, where the icon is searched. + * @param dirs A couple of directories below icons/ in the plugin. If loading fails, + * the next dir will be taken as fallback. + * @param name The name of the file defining the icon. The name will be used as + * key. + */ + protected void externalImage(String key, String plugin, String[] dirs, String name) { + if (plugin != null) { + fPlugins.put(key, plugin); + } + String[] locations = new String[dirs.length]; + for (int i = 0; i < dirs.length; i++) { + String dir = dirs[i]; + if (dir== null || dir.equals(""))//$NON-NLS-1$ + locations[i] = "icons/" + name; //$NON-NLS-1$ + else + locations[i] = "icons/" + dir + "/" + name; //$NON-NLS-1$ //$NON-NLS-2$ + } + fLocations.put(key, locations); + } + + final private Image internalDoGet(String key) { + // First query the parent (local) image registry if + // an image for the given key is registered. + Image i = super.get(key); + if (i != null) return i; + + // If no image had been returned, try the delegates + for (ImageRegistry delegate : fDelegates) { + i = delegate.get(key); + if (i != null) break; + } + + return i; + } + + final private ImageDescriptor internalDoGetDescriptor(String key) { + // First query the parent (local) image registry if + // an image for the given key is registered. + ImageDescriptor d = super.getDescriptor(key); + if (d != null) return d; + + // If no image had been returned, try the delegates + for (ImageRegistry delegate : fDelegates) { + d = delegate.getDescriptor(key); + if (d != null) break; + } + + return d; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.resource.ImageRegistry#get(java.lang.String) + */ + @Override + final public Image get(String key) { + Image i = internalDoGet(key); + if (i != null) { + return i; + } + + ImageDescriptor d = createFileImageDescriptor(key); + if (d != null) { + put(key, d); + return internalDoGet(key); + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.resource.ImageRegistry#getDescriptor(java.lang.String) + */ + @Override + final public ImageDescriptor getDescriptor(String key) { + ImageDescriptor d = internalDoGetDescriptor(key); + if (d != null) { + return d; + } + + d = createFileImageDescriptor(key); + if (d != null) { + put(key, d); + return d; + } + return null; + } + + private ImageDescriptor createFileImageDescriptor(String key) { + URL url = fBaseUrl; + String pluginId = fPlugins.get(key); + if (pluginId != null) { + Bundle bundle= Platform.getBundle(pluginId); + if (bundle != null) { + url = bundle.getEntry("/"); //$NON-NLS-1$ + } + } + String[] locations= fLocations.get(key); + if (locations != null) { + for (int i = 0; i < locations.length; i++) { + String loc = locations[i]; + URL full; + try { + full = new URL(url, loc); + ImageDescriptor candidate = ImageDescriptor.createFromURL(full); + if (candidate != null && candidate.getImageData() != null) { + return candidate; + } + } catch (MalformedURLException e) { + IStatus status = new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), + Messages.AbstractImageRegistry_error_malformedImage, e); + UIPlugin.getDefault().getLog().log(status); + } catch (SWTException e) { + // try the next one. + } + } + } + return null; + } + + /** + * Get a shared Image for a given descriptor + */ + public Image getSharedImage(AbstractImageDescriptor d) { + String key = d.getKey(); + Image shared = super.get(key); + if (shared != null) { + return shared; + } + put(key, d); + return super.get(key); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/interfaces/IUIConstants.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/interfaces/IUIConstants.java new file mode 100644 index 000000000..3ff613ac9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/interfaces/IUIConstants.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.interfaces; + +import org.eclipse.tm.te.ui.activator.UIPlugin; + +/** + * Target Explorer: Common UI constants. + * + * @author uwe.stieber@windriver.com + */ +public interface IUIConstants { + + /** + * The Target Explorer common controls context menu id base part. + */ + public static final String ID_CONTROL_MENUS_BASE = UIPlugin.getUniqueIdentifier() + ".controls"; //$NON-NLS-1$ +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.java new file mode 100644 index 000000000..297235b6b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.nls; + +import org.eclipse.osgi.util.NLS; + +/** + * Target Explorer: Common UI plugin externalized strings management. + */ +public class Messages extends NLS { + + // The plug-in resource bundle name + private static final String BUNDLE_NAME = "org.eclipse.tm.te.ui.nls.Messages"; //$NON-NLS-1$ + + /** + * Static constructor. + */ + static { + // Load message values from bundle file + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + // **** Declare externalized string id's down here ***** + + public static String AbstractImageRegistry_error_malformedImage; + + public static String NodePropertiesTableControl_section_title; + public static String NodePropertiesTableControl_section_title_noSelection; + public static String NodePropertiesTableControl_column_name_label; + public static String NodePropertiesTableControl_column_value_label; + + public static String PendingOperation_label; + + public static String EditBrowseTextControl_button_label; +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.properties new file mode 100644 index 000000000..b943bab0c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.properties @@ -0,0 +1,15 @@ +# +# org.eclipse.tm.te.ui +# Externalized Strings. +# + +AbstractImageRegistry_error_malformedImage=Malformed Image + +NodePropertiesTableControl_section_title={0} Information +NodePropertiesTableControl_section_title_noSelection=Node +NodePropertiesTableControl_column_name_label=Property +NodePropertiesTableControl_column_value_label=Value + +PendingOperation_label=Pending... + +EditBrowseTextControl_button_label=Browse... diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nodes/PendingOperation.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nodes/PendingOperation.java new file mode 100644 index 000000000..1859001c6 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nodes/PendingOperation.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.nodes; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.tm.te.ui.nls.Messages; + + +/** + * Target Explorer: Pending operation data node. + */ +public class PendingOperation extends PlatformObject { + + /** + * Returns the pending operation node name. + * + * @return The node name. + */ + public final String getName() { + return Messages.PendingOperation_label; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public final int hashCode() { + return getName().hashCode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public final String toString() { + return getName(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableNode.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableNode.java new file mode 100644 index 000000000..e4daa98c9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableNode.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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.tables; + +import org.eclipse.core.runtime.PlatformObject; + +/** + * Target Explorer: Immutable representation of a table node. + */ +public final class TableNode extends PlatformObject { + /** + * The node name. + */ + public final String name; + + /** + * The node value. + */ + public final String value; + + /** + * Constructor. + * + * @param name The node name. Must be not <code>null</code>. + * @param value The node value. Must be not <code>null</code>. + */ + public TableNode(String name, String value) { + assert name != null && value != null; + this.name = name; + this.value = value; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableViewerComparator.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableViewerComparator.java new file mode 100644 index 000000000..c00691b66 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableViewerComparator.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.tables; + +import java.util.Arrays; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Table; +import org.eclipse.tm.te.ui.AbstractViewerComparator; + + +/** + * Target Explorer: Common table control viewer comparator implementation. + */ +public class TableViewerComparator extends AbstractViewerComparator { + private final ITableLabelProvider fLabelProvider; + + /** + * Constructor. + * + * @param viewer The parent viewer. Must be not <code>null</code>. + * @param labelProvider The table label provider. Must be not <code>null</code>. + */ + public TableViewerComparator(Viewer viewer, ITableLabelProvider labelProvider) { + super(viewer); + assert labelProvider != null; + fLabelProvider = labelProvider; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doDetermineInverter(org.eclipse.jface.viewers.Viewer) + */ + @Override + protected int doDetermineInverter(Viewer viewer) { + int inverter = 1; + + // Viewer must be of type TableViewer and the table must not be disposed yet + if (viewer instanceof TableViewer && ((TableViewer)viewer).getTable() != null) { + Table table = ((TableViewer)viewer).getTable(); + if (!table.isDisposed() && table.getSortDirection() == SWT.DOWN) inverter = -1; + } + + return inverter; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetText(java.lang.Object, int) + */ + @Override + protected String doGetText(Object node, int index) { + if (node != null && fLabelProvider != null) { + return index != -1 ? fLabelProvider.getColumnText(node, index) : ((ILabelProvider)fLabelProvider).getText(node); + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetSortColumnLabel(org.eclipse.jface.viewers.Viewer) + */ + @Override + protected String doGetSortColumnLabel(Viewer viewer) { + // Viewer must be of type TableViewer and the table must not be disposed yet + if (viewer instanceof TableViewer && ((TableViewer)viewer).getTable() != null && !((TableViewer)viewer).getTable().isDisposed()) { + Table table = ((TableViewer)viewer).getTable(); + return table.getSortColumn() != null ? table.getSortColumn().getText() : ""; //$NON-NLS-1$ + } + return ""; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetSortColumnIndex(org.eclipse.jface.viewers.Viewer) + */ + @Override + protected int doGetSortColumnIndex(Viewer viewer) { + // Viewer must be of type TableViewer and the table must not be disposed yet + if (viewer instanceof TableViewer && ((TableViewer)viewer).getTable() != null && !((TableViewer)viewer).getTable().isDisposed()) { + Table table = ((TableViewer)viewer).getTable(); + return table.getSortColumn() != null ? Arrays.asList(table.getColumns()).indexOf(table.getSortColumn()) : -1; + } + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doCompare(java.lang.Object, java.lang.Object, java.lang.String, int, int) + */ + @SuppressWarnings("unchecked") + @Override + protected int doCompare(Object node1, Object node2, String sortColumn, int index, int inverter) { + if (node1 == null && node2 == null) return 0; + if (node1 != null && node2 == null) return 1; + if (node1 == null && node2 != null) return -1; + + // Get the labels + String text1 = doGetText(node1, index); + String text2 = doGetText(node2, index); + + // If the text is matching ".*[0-9]+$" -> compare numerical instead of alphabetical + if (text1 != null && text1.matches(".*[0-9]+$") && text2 != null && text2.matches(".*[0-9]+$")) { //$NON-NLS-1$ //$NON-NLS-2$ + // Split numbers and text (note that this effectively removes the number ... splitted[1] == ""). + String[] splitted1 = text1.split("[0-9]+$", 2); //$NON-NLS-1$ + String[] splitted2 = text2.split("[0-9]+$", 2); //$NON-NLS-1$ + + // Get the parts to match alphabetical + String alpha1 = splitted1[0]; + String alpha2 = splitted2[0]; + + // The numerical parts is what remains if we strip the alpha parts from the original text + String num1 = text1.replace(alpha1, ""); //$NON-NLS-1$ + String num2 = text2.replace(alpha2, ""); //$NON-NLS-1$ + + // Compare the alpha parts + int result = getComparator().compare(alpha1, alpha2) * inverter; + // Only if the alpha parts are equal, compare the numerical parts too + if (result == 0) { + result = Integer.decode(num1).compareTo(Integer.decode(num2)) * inverter; + } + + return result; + } + + // Compare the text alphabetical + return getComparator().compare(text1, text2) * inverter; + } +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/properties/NodePropertiesTableControl.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/properties/NodePropertiesTableControl.java new file mode 100644 index 000000000..4fe2f3d68 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/properties/NodePropertiesTableControl.java @@ -0,0 +1,417 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.tables.properties; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableLayout; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.tm.te.ui.WorkbenchPartControl; +import org.eclipse.tm.te.ui.forms.CustomFormToolkit; +import org.eclipse.tm.te.ui.interfaces.IUIConstants; +import org.eclipse.tm.te.ui.nls.Messages; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.forms.widgets.Section; + + +/** + * Target Explorer: Abstract node properties table control implementation. + */ +public abstract class NodePropertiesTableControl extends WorkbenchPartControl { + // Reference to the table viewer + private TableViewer fViewer; + // Reference to the selection changed listener + private ISelectionChangedListener fEditorSelectionChangedListener; + + // We remember the sorting order (ascending vs. descending) for each + // column separately. That way we can come up with the sort order switching + // correctly if the user changes from one column to the next. If set + // to Boolean.FALSE, the sort order for the column is descending (default) + private final Map<TableColumn, Boolean> fColumnSortOrder = new LinkedHashMap<TableColumn, Boolean>(); + + /** + * Default node properties table control selection changed listener implementation. + * The selection changed listener is registered to the editor tree control. + */ + protected class NodePropertiesTableControlSelectionChangedListener implements ISelectionChangedListener { + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) + */ + public void selectionChanged(SelectionChangedEvent event) { + if (getViewer() != null) { + getViewer().setInput(event.getSelection()); + } + } + } + + /** + * Constructor. + * + * @param parentPart The parent workbench part this control is embedded in or <code>null</code>. + */ + public NodePropertiesTableControl(IWorkbenchPart parentPart) { + super(parentPart); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.WorkbenchPartControl#dispose() + */ + @Override + public void dispose() { + // Dispose the editor tree control selection changed listener + if (fEditorSelectionChangedListener != null) { + ISelectionProvider selectionProvider = (ISelectionProvider)getParentPart().getAdapter(ISelectionProvider.class); + if (selectionProvider != null) { + selectionProvider.removeSelectionChangedListener(fEditorSelectionChangedListener); + fEditorSelectionChangedListener = null; + } + } + + super.dispose(); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.WorkbenchPartControl#setupFormPanel(org.eclipse.swt.widgets.Composite, org.eclipse.tm.te.ui.forms.CustomFormToolkit) + */ + @Override + public void setupFormPanel(Composite parent, CustomFormToolkit toolkit) { + super.setupFormPanel(parent, toolkit); + + // Create the table viewer + fViewer = doCreateTableViewer(parent); + // Configure the table viewer + configureTableViewer(fViewer); + // Configure the table + configureTable(fViewer.getTable(), fViewer.getComparator() != null); + + // Register the control as selection listener to the editor control + ISelectionProvider selectionProvider = getParentPart() != null ? (ISelectionProvider)getParentPart().getAdapter(ISelectionProvider.class) : null; + if (selectionProvider != null) { + // Create the selection changed listener instance + fEditorSelectionChangedListener = doCreateEditorSelectionChangedListener(); + selectionProvider.addSelectionChangedListener(fEditorSelectionChangedListener); + } + + // Prepare popup menu and toolbar + createContributionItems(fViewer); + + // Set the current selection as input + fViewer.setInput(selectionProvider != null ? selectionProvider.getSelection() : null); + } + + /** + * Creates a new editor tree control selection changed listener instance. + * + * @return The editor tree control selection changed listener instance. + */ + protected ISelectionChangedListener doCreateEditorSelectionChangedListener() { + return new NodePropertiesTableControlSelectionChangedListener(); + } + + /** + * Creates the table viewer instance. + * + * @param parent The parent composite. Must not be <code>null</code>. + * @return The table viewer. + */ + protected TableViewer doCreateTableViewer(Composite parent) { + assert parent != null; + + TableViewer tableViewer = new TableViewer(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER); + + return tableViewer; + } + + /** + * Configure the table Viewer. + * + * @param tableViewer The table viewer. Must not be <code>null</code>. + */ + protected void configureTableViewer(TableViewer tableViewer) { + assert tableViewer != null; + + tableViewer.setLabelProvider(doCreateTableViewerLabelProvider(tableViewer)); + tableViewer.setContentProvider(doCreateTableViewerContentProvider(tableViewer)); + tableViewer.setComparator(doCreateTableViewerComparator(tableViewer)); + } + + /** + * Creates the table viewer label provider instance. + * + * @param viewer The table viewer. Must be not <code>null</code>. + * @return The table viewer label provider instance. + */ + protected abstract ITableLabelProvider doCreateTableViewerLabelProvider(TableViewer viewer); + + /** + * Creates the table viewer content provider instance. + * + * @param viewer The table viewer. Must be not <code>null</code>. + * @return The table viewer content provider instance. + */ + protected abstract IStructuredContentProvider doCreateTableViewerContentProvider(TableViewer viewer); + + /** + * Creates the table viewer comparator instance. + * + * @param viewer The table viewer. Must be not <code>null</code>. + * @return The table viewer comparator instance or <code>null</code> to turn of sorting. + */ + protected ViewerComparator doCreateTableViewerComparator(TableViewer viewer) { + return null; + } + + /** + * Configure the table. + * + * @param table The table. Must not be <code>null</code>. + * @param sorted Specify <code>true</code> if the table shall support sorting, <code>false</code> otherwise. + */ + protected void configureTable(Table table, boolean sorted) { + assert table != null; + + // Create and configure the table columns + createTableColumns(table, sorted); + + table.setHeaderVisible(true); + table.setLinesVisible(true); + } + + /** + * Create the table columns. + * + * @param table The table. Must not be <code>null</code>. + * @param sorted Specify <code>true</code> if the table shall support sorting, <code>false</code> otherwise. + */ + protected void createTableColumns(final Table table, boolean sorted) { + assert table != null; + + TableColumn sortColumn = null; + + TableColumn column = new TableColumn(table, SWT.LEFT); + column.setText(Messages.NodePropertiesTableControl_column_name_label); + fColumnSortOrder.put(column, Boolean.TRUE); + if (sorted) column.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + if (e.widget instanceof TableColumn) { + switchSortColumn(table, (TableColumn)e.widget); + } + } + }); + // The property name is the default sorting column + sortColumn = column; + + column = new TableColumn(table, SWT.LEFT); + column.setText(Messages.NodePropertiesTableControl_column_value_label); + fColumnSortOrder.put(column, Boolean.FALSE); + if (sorted) column.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + if (e.widget instanceof TableColumn) { + switchSortColumn(table, (TableColumn)e.widget); + } + } + }); + + TableLayout tableLayout = new TableLayout(); + tableLayout.addColumnData(new ColumnWeightData(30)); + tableLayout.addColumnData(new ColumnWeightData(70)); + table.setLayout(tableLayout); + + GridData layoutData = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING); + table.setLayoutData(layoutData); + + if (sorted) { + // set the default sort column + table.setSortColumn(sortColumn); + table.setSortDirection(fColumnSortOrder.get(sortColumn).booleanValue() ? SWT.UP : SWT.DOWN); + } + } + + /** + * Switches the sort order for the given column and set the + * new sort order and sort column to the given table. + * + * @param table The table. + * @param column The table column + */ + protected final void switchSortColumn(Table table, TableColumn column) { + if (table == null || table.isDisposed() || column == null || column.isDisposed()) { + return; + } + // Get the current sorting order for the given column + boolean newSortOrder = !fColumnSortOrder.get(column).booleanValue(); + // Set sort column and sort direction + table.setSortColumn(column); + table.setSortDirection(newSortOrder ? SWT.UP : SWT.DOWN); + // And update the remembered sort order in the map + fColumnSortOrder.put(column, Boolean.valueOf(newSortOrder)); + + getViewer().refresh(); + } + + /** + * Create the context menu and toolbar groups. + * + * @param viewer The table viewer. Must not be <code>null</code>. + */ + protected void createContributionItems(TableViewer viewer) { + assert viewer != null; + + // Create the menu manager + MenuManager manager = new MenuManager("#PopupMenu"); //$NON-NLS-1$ + // Attach the menu listener + manager.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + } + }); + // All items are removed when menu is closing + manager.setRemoveAllWhenShown(true); + // Associated with the tree + viewer.getTable().setMenu(manager.createContextMenu(viewer.getTable())); + + // Register the context menu at the parent workbench part site. + if (getParentPart() != null && getParentPart().getSite() != null && getContextMenuId() != null) { + IWorkbenchPartSite site = getParentPart().getSite(); + site.registerContextMenu(getContextMenuId(), manager, viewer); + } + + // The toolbar is a bit more complicated as we want to have the + // toolbar placed within the section title. + createToolbarContributionItem(viewer); + } + + /** + * Returns the controls context menu id. + * + * @return The context menu id or <code>null</code>. + */ + protected String getContextMenuId() { + return IUIConstants.ID_CONTROL_MENUS_BASE + ".menu.propertiesTable"; //$NON-NLS-1$ + } + + /** + * Creates the toolbar within the section parent of the given filtered tree. + * + * @param viewer The table viewer. Must not be <code>null</code>. + */ + protected void createToolbarContributionItem(TableViewer viewer) { + assert viewer != null; + + // Determine the section parent from the filtered tree + Composite parent = viewer.getTable().getParent(); + while (parent != null && !(parent instanceof Section)) { + parent = parent.getParent(); + } + + // We are done here if we cannot find a section parent or the parent is disposed + if (parent == null || parent.isDisposed()) { + return; + } + + // Create the toolbar control + ToolBar toolbar = new ToolBar(parent, SWT.FLAT | SWT.HORIZONTAL | SWT.RIGHT); + + // The cursor within the toolbar shall change to an hand + final Cursor handCursor = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND); + toolbar.setCursor(handCursor); + // Cursor needs to be explicitly disposed + toolbar.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + if ((handCursor != null) && (handCursor.isDisposed() == false)) { + handCursor.dispose(); + } + } + }); + + // If the parent composite is a forms section, set the toolbar + // as text client to the section header + if (parent instanceof Section) { + Section section = (Section)parent; + // Set the toolbar as text client + section.setTextClient(toolbar); + } + + // create the toolbar items + createToolBarItems(toolbar); + } + + /** + * Create the toolbar items to be added to the toolbar. Override + * to add the wanted toolbar items. + * <p> + * <b>Note:</b> The toolbar items are added from left to right. + * + * @param toolbar The toolbar to add the toolbar items too. Must not be <code>null</code>. + */ + protected void createToolBarItems(ToolBar toolbar) { + assert toolbar != null; + } + + /** + * Returns the viewer instance. + * + * @return The viewer instance or <code>null</code>. + */ + public Viewer getViewer() { + return fViewer; + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) + */ + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Object getAdapter(Class adapter) { + if (Viewer.class.isAssignableFrom(adapter)) { + // We have to double check if our real viewer is assignable to + // the requested Viewer class. + Viewer viewer = getViewer(); + if (!adapter.isAssignableFrom(viewer.getClass())) { + viewer = null; + } + return viewer; + } else if (ISelectionListener.class.isAssignableFrom(adapter)) { + return fEditorSelectionChangedListener; + } + + return super.getAdapter(adapter); + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/AbstractTreeControl.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/AbstractTreeControl.java new file mode 100644 index 000000000..e4ae46050 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/AbstractTreeControl.java @@ -0,0 +1,307 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.trees; + + +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.tm.te.ui.WorkbenchPartControl; +import org.eclipse.tm.te.ui.forms.CustomFormToolkit; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.forms.widgets.Section; + + +/** + * Target Explorer: Abstract tree control implementation. + */ +public abstract class AbstractTreeControl extends WorkbenchPartControl { + // Reference to the tree viewer instance + private TreeViewer fViewer; + // Reference to the selection changed listener + private ISelectionChangedListener fSelectionChangedListener; + + /** + * Constructor. + */ + public AbstractTreeControl() { + super(); + } + + /** + * Constructor. + * + * @param parentPart The parent workbench part this control is embedded in or <code>null</code>. + */ + public AbstractTreeControl(IWorkbenchPart parentPart) { + super(parentPart); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.WorkbenchPartControl#dispose() + */ + @Override + public void dispose() { + // Unregister the selection changed listener + if (fSelectionChangedListener != null) { + if (getViewer() != null) { + getViewer().removeSelectionChangedListener(fSelectionChangedListener); + } + fSelectionChangedListener = null; + } + + super.dispose(); + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.WorkbenchPartControl#setupFormPanel(org.eclipse.swt.widgets.Composite, org.eclipse.tm.te.ui.forms.CustomFormToolkit) + */ + @Override + public void setupFormPanel(Composite parent, CustomFormToolkit toolkit) { + super.setupFormPanel(parent, toolkit); + + // Create the tree viewer + fViewer = doCreateTreeViewer(parent); + // And configure the tree viewer + configureTreeViewer(fViewer); + + // Prepare popup menu and toolbar + createContributionItems(fViewer); + } + + /** + * Creates the tree viewer instance. + * + * @param parent The parent composite. Must be not <code>null</code>. + * @return The tree viewer. + */ + protected TreeViewer doCreateTreeViewer(Composite parent) { + assert parent != null; + return new TreeViewer(parent, SWT.FULL_SELECTION | SWT.SINGLE); + } + + /** + * Configure the tree viewer. + * + * @param viewer The tree viewer. Must be not <code>null</code>. + */ + protected void configureTreeViewer(TreeViewer viewer) { + assert viewer != null; + + viewer.setAutoExpandLevel(getAutoExpandLevel()); + + viewer.setLabelProvider(doCreateTreeViewerLabelProvider(viewer)); + viewer.setContentProvider(doCreateTreeViewerContentProvider(viewer)); + viewer.setComparator(doCreateTreeViewerComparator(viewer)); + + viewer.getTree().setLayoutData(doCreateTreeViewerLayoutData(viewer)); + + // Attach the selection changed listener + fSelectionChangedListener = doCreateTreeViewerSelectionChangedListener(viewer); + if (fSelectionChangedListener != null) { + viewer.addSelectionChangedListener(fSelectionChangedListener); + } + } + + /** + * Returns the number of levels to auto expand. + * If the method returns <code>0</code>, no auto expansion will happen + * + * @return The number of levels to auto expand or <code>0</code>. + */ + protected int getAutoExpandLevel() { + return 2; + } + + /** + * Creates the tree viewer layout data instance. + * + * @param viewer The tree viewer. Must be not <code>null</code>. + * @return The tree viewer layout data instance. + */ + protected Object doCreateTreeViewerLayoutData(TreeViewer viewer) { + return new GridData(GridData.FILL_BOTH); + } + + /** + * Creates the tree viewer label provider instance. + * + * @param viewer The tree viewer. Must be not <code>null</code>. + * @return The tree viewer label provider instance. + */ + protected abstract ILabelProvider doCreateTreeViewerLabelProvider(TreeViewer viewer); + + /** + * Creates the tree viewer content provider instance. + * + * @param viewer The tree viewer. Must be not <code>null</code>. + * @return The tree viewer content provider instance. + */ + protected abstract ITreeContentProvider doCreateTreeViewerContentProvider(TreeViewer viewer); + + /** + * Creates the tree viewer comparator instance. + * + * @param viewer The tree viewer. Must be not <code>null</code>. + * @return The tree viewer comparator instance or <code>null</code> to turn of sorting. + */ + protected ViewerComparator doCreateTreeViewerComparator(TreeViewer viewer) { + assert viewer != null; + return null; + } + + /** + * Creates a new selection changed listener instance. + * + * @param viewer The tree viewer. Must be not <code>null</code>. + * @return The selection changed listener instance. + */ + protected abstract ISelectionChangedListener doCreateTreeViewerSelectionChangedListener(TreeViewer viewer); + + /** + * Create the context menu and toolbar groups. + * + * @param viewer The tree viewer instance. Must not be <code>null</code>. + */ + protected void createContributionItems(TreeViewer viewer) { + assert viewer != null; + + // Create the menu manager + MenuManager manager = new MenuManager("#PopupMenu"); //$NON-NLS-1$ + // Attach the menu listener + manager.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + } + }); + // All items are removed when menu is closing + manager.setRemoveAllWhenShown(true); + // Associated with the tree + viewer.getTree().setMenu(manager.createContextMenu(viewer.getTree())); + + // Register the context menu at the parent workbench part site. + if (getParentPart() != null && getParentPart().getSite() != null && getContextMenuId() != null) { + getParentPart().getSite().registerContextMenu(getContextMenuId(), manager, viewer); + } + + // The toolbar is a bit more complicated as we want to have the + // toolbar placed within the section title. + createToolbarContributionItem(viewer); + } + + /** + * Returns the context menu id. + * + * @return The context menu id. + */ + protected abstract String getContextMenuId(); + + /** + * Creates the toolbar within the section parent of the given tree viewer. + * + * @param viewer The tree viewer instance. Must not be <code>null</code>. + */ + protected void createToolbarContributionItem(TreeViewer viewer) { + assert viewer != null; + + // Determine the section parent from the tree viewer + Composite parent = viewer.getTree().getParent(); + while (parent != null && !(parent instanceof Section)) { + parent = parent.getParent(); + } + + // We are done here if we cannot find a section parent or the parent is disposed + if (parent == null || parent.isDisposed()) { + return; + } + + // Create the toolbar control + ToolBar toolbar = new ToolBar(parent, SWT.FLAT | SWT.HORIZONTAL | SWT.RIGHT); + + // The cursor within the toolbar shall change to an hand + final Cursor handCursor = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND); + toolbar.setCursor(handCursor); + // Cursor needs to be explicitly disposed + toolbar.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + if ((handCursor != null) && (handCursor.isDisposed() == false)) { + handCursor.dispose(); + } + } + }); + + // If the parent composite is a forms section, set the toolbar + // as text client to the section header + if (parent instanceof Section) { + Section section = (Section)parent; + // Set the toolbar as text client + section.setTextClient(toolbar); + } + + // create the toolbar items + createToolBarItems(toolbar); + } + + /** + * Create the toolbar items to be added to the toolbar. Override + * to add the wanted toolbar items. + * <p> + * <b>Note:</b> The toolbar items are added from left to right. + * + * @param toolbar The toolbar to add the toolbar items too. Must not be <code>null</code>. + */ + protected void createToolBarItems(ToolBar toolbar) { + assert toolbar != null; + } + + /** + * Returns the viewer instance. + * + * @return The viewer instance or <code>null</code>. + */ + public Viewer getViewer() { + return fViewer; + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) + */ + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Object getAdapter(Class adapter) { + if (Viewer.class.isAssignableFrom(adapter)) { + // We have to double check if our real viewer is assignable to + // the requested Viewer class. + Viewer viewer = getViewer(); + if (!adapter.isAssignableFrom(viewer.getClass())) { + viewer = null; + } + return viewer; + } + + return super.getAdapter(adapter); + } + +} diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/TreeViewerComparator.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/TreeViewerComparator.java new file mode 100644 index 000000000..b24a4b2af --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/TreeViewerComparator.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * 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: + * Uwe Stieber (Wind River) - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.te.ui.trees; + +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.tm.te.ui.AbstractViewerComparator; + + +/** + * Target Explorer: Common tree control viewer comparator implementation. + */ +public class TreeViewerComparator extends AbstractViewerComparator { + private final ILabelProvider fLabelProvider; + + /** + * Constructor. + * + * @param viewer The parent viewer. Must be not <code>null</code>. + * @param labelProvider The label provider. Must be not <code>null</code>. + */ + public TreeViewerComparator(Viewer viewer, ILabelProvider labelProvider) { + super(viewer); + assert labelProvider != null; + fLabelProvider = labelProvider; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doDetermineInverter(org.eclipse.jface.viewers.Viewer) + */ + @Override + protected int doDetermineInverter(Viewer viewer) { + int inverter = 1; + + // Viewer must be of type TreeViewer and the tree must not be disposed yet + if (viewer instanceof TreeViewer && ((TreeViewer)viewer).getTree() != null) { + Tree tree = ((TreeViewer)viewer).getTree(); + if (!tree.isDisposed() && tree.getSortDirection() == SWT.DOWN) inverter = -1; + } + + return inverter; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetText(java.lang.Object, int) + */ + @Override + protected String doGetText(Object node, int index) { + if (node != null && fLabelProvider != null) { + return fLabelProvider.getText(node); + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetSortColumnLabel(org.eclipse.jface.viewers.Viewer) + */ + @Override + protected String doGetSortColumnLabel(Viewer viewer) { + // Viewer must be of type TreeViewer and the tree must not be disposed yet + if (viewer instanceof TreeViewer && ((TreeViewer)viewer).getTree() != null && !((TreeViewer)viewer).getTree().isDisposed()) { + Tree tree = ((TreeViewer)viewer).getTree(); + return tree.getSortColumn() != null ? tree.getSortColumn().getText() : ""; //$NON-NLS-1$ + } + return ""; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetSortColumnIndex(org.eclipse.jface.viewers.Viewer) + */ + @Override + protected int doGetSortColumnIndex(Viewer viewer) { + if (viewer instanceof TreeViewer && ((TreeViewer)viewer).getTree() != null && !((TreeViewer)viewer).getTree().isDisposed()) { + Tree tree = ((TreeViewer)viewer).getTree(); + return tree.getSortColumn() != null ? Arrays.asList(tree.getColumns()).indexOf(tree.getSortColumn()) : -1; + } + return -1; + } + + /* (non-Javadoc) + * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doCompare(java.lang.Object, java.lang.Object, java.lang.String, int, int) + */ + @SuppressWarnings("unchecked") + @Override + protected int doCompare(Object node1, Object node2, String sortColumn, int index, int inverter) { + if (node1 == null && node2 == null) return 0; + if (node1 != null && node2 == null) return 1; + if (node1 == null && node2 != null) return -1; + + // Get the labels + String text1 = doGetText(node1, index); + String text2 = doGetText(node2, index); + + // Normalize labels + if (text1 == null) text1 = ""; //$NON-NLS-1$ + if (text2 == null) text2 = ""; //$NON-NLS-1$ + + // The tree sorts not strictly alphabetical. First comes entries starting with numbers, + // second entries starting with uppercase and than all the rest. Additional, if a label contains + // uppercase characters, it is sorted in before any labels being lowercase only. + if (text1.length() > 0 && text2.length() > 0) { + // Get the first characters of both + char c1 = text1.charAt(0); + char c2 = text2.charAt(0); + + if (Character.isDigit(c1) || Character.isDigit(c2)) { + // Check on the differences. If both are digits, the standard compare will do it + if (Character.isDigit(c1) && !Character.isDigit(c2)) return -1 * inverter; + if (!Character.isDigit(c1) && Character.isDigit(c2)) return 1 * inverter; + } + + if (Character.isUpperCase(c1) || Character.isUpperCase(c2)) { + // Check on the differences. If both are uppercase characters, the standard compare will do it + if (Character.isUpperCase(c1) && !Character.isUpperCase(c2)) return -1 * inverter; + if (!Character.isUpperCase(c1) && Character.isUpperCase(c2)) return 1 * inverter; + } + + Matcher m1 = Pattern.compile("(\\D+)(\\d+)").matcher(text1); //$NON-NLS-1$ + Matcher m2 = Pattern.compile("(\\D+)(\\d+)").matcher(text2); //$NON-NLS-1$ + if (m1.matches() && m2.matches()) { + String p11 = m1.group(1); + String p12 = m1.group(2); + + String p21 = m2.group(1); + String p22 = m2.group(2); + + if (p11 != null && p11.equals(p21)) { + // Compare the second parts as number + try { + int result = 0; + long l1 = Long.parseLong(p12); + long l2 = Long.parseLong(p22); + + if (l1 > l2) result = 1; + if (l1 < l2) result = -1; + + return result; + } catch (NumberFormatException e) { /* ignored on purpose */ } + } + } + + if (text1.matches(".*[A-Z]+.*") || text2.matches(".*[A-Z]+.*")) { //$NON-NLS-1$ //$NON-NLS-2$ + if (text1.matches(".*[A-Z]+.*") && !text2.matches(".*[A-Z]+.*")) return -1 * inverter; //$NON-NLS-1$ //$NON-NLS-2$ + if (!text1.matches(".*[A-Z]+.*") && text2.matches(".*[A-Z]+.*")) return 1 * inverter; //$NON-NLS-1$ //$NON-NLS-2$ + + // Additionally, it even depends on the position of the first uppercase + // character if both strings contains them :-( + int minLength = Math.min(text1.length(), text2.length()); + for (int i = 0; i < minLength; i++) { + char ch1 = text1.charAt(i); + char ch2 = text2.charAt(i); + + if (Character.isUpperCase(ch1) && !Character.isUpperCase(ch2)) return -1 * inverter; + if (!Character.isUpperCase(ch1) && Character.isUpperCase(ch2)) return 1 * inverter; + // If both are uppercase, we break the loop and compare as usual + if (Character.isUpperCase(ch1) && Character.isUpperCase(ch2)) break; + } + } + } + + // Compare the text alphabetical + return getComparator().compare(text1, text2) * inverter; + } +} |