diff options
author | Uwe Stieber | 2012-02-19 16:45:27 +0000 |
---|---|---|
committer | Uwe Stieber | 2012-02-19 16:45:27 +0000 |
commit | b953bce70507af630a13163d6b82868f9b5e7711 (patch) | |
tree | de7baf9edefb6b9d3ae816ce9cb22506bea5e4cf /target_explorer/plugins | |
parent | 71bd059af3fb739c3a2ba6859e5b6a94243ec905 (diff) | |
download | org.eclipse.tcf-b953bce70507af630a13163d6b82868f9b5e7711.tar.gz org.eclipse.tcf-b953bce70507af630a13163d6b82868f9b5e7711.tar.xz org.eclipse.tcf-b953bce70507af630a13163d6b82868f9b5e7711.zip |
Target Explorer: Continued launch context selector work
Diffstat (limited to 'target_explorer/plugins')
18 files changed, 936 insertions, 29 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/lm/interfaces/IContextSelectorLaunchAttributes.java b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/lm/interfaces/IContextSelectorLaunchAttributes.java new file mode 100644 index 000000000..f1730858c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/lm/interfaces/IContextSelectorLaunchAttributes.java @@ -0,0 +1,24 @@ +/*******************************************************************************
+ * Copyright (c) 2012 Wind River Systems, Inc. and others. All rights reserved.
+ * This program and the accompanying materials are made available under the terms
+ * of the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.launch.core.lm.interfaces;
+
+/**
+ * Defines the launch configuration attribute id's to access the launch step contexts.
+ */
+public interface IContextSelectorLaunchAttributes {
+
+ /**
+ * Launch configuration attribute: The launch contexts the launch is operating with. Use
+ * {@link ContextSelectorPersistanceDelegate} to access
+ * this attribute within a launch configuration.
+ */
+ public static final String ATTR_LAUNCH_CONTEXTS = ICommonLaunchAttributes.ATTR_PREFIX + ".launch_contexts"; //$NON-NLS-1$
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/persistence/ContextSelectorPersistenceDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/persistence/ContextSelectorPersistenceDelegate.java new file mode 100644 index 000000000..c26a521d9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/persistence/ContextSelectorPersistenceDelegate.java @@ -0,0 +1,528 @@ +/******************************************************************************* + * Copyright (c) 2012 Wind River Systems, Inc. and others. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.launch.core.persistence; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.tcf.te.launch.core.activator.CoreBundleActivator; +import org.eclipse.tcf.te.launch.core.lm.interfaces.IContextSelectorLaunchAttributes; +import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification; +import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode; +import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext; +import org.osgi.framework.Bundle; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Context selector persistence delegate. + */ +public class ContextSelectorPersistenceDelegate { + // The read cache for step contexts. Avoid running time consuming + // re-parsing of an already parsed step context description again and again. + private final static Map<String, List<IStepContext>> readCache = new LinkedHashMap<String, List<IStepContext>>(); + // The write cache for target contexts. Avoids re-generating the XML again and again. + private final static Map<String, String> writeCache = new LinkedHashMap<String, String>(); + + // Limit the read cache to the last 10 read step contexts + private final static int READ_CACHE_MAX_CAPACITY = 25; + // Limit the write cache to the last 10 written step contexts + private final static int WRITE_CACHE_MAX_CAPACITY = 25; + + /** + * Saves the selected launch contexts to the specified launch configuration working copy. If the + * selected launch contexts are <code>null</code> or empty, the attribute will be removed from + * the specified launch configuration working copy. + * + * @param wc The launch configuration working copy. Must not be <code>null</code>. + * @param contexts The launch contexts to save or <code>null</code>. + */ + public final static void setLaunchContexts(ILaunchConfigurationWorkingCopy wc, IStepContext[] contexts) { + Assert.isNotNull(wc); + + if (contexts == null || contexts.length == 0) { + DefaultPersistenceDelegate.setAttribute(wc, IContextSelectorLaunchAttributes.ATTR_LAUNCH_CONTEXTS, (String) null); + return; + } + + // Get the encoded XML representation + String xml = encodeLaunchContexts(contexts); + // And save them to the launch configuration. If XML == null, the + // launch contexts will be removed from the launch configuration + DefaultPersistenceDelegate.setAttribute(wc, IContextSelectorLaunchAttributes.ATTR_LAUNCH_CONTEXTS, xml); + } + + /** + * Saves the selected launch contexts to the specified launch specification. If the selected + * launch contexts are <code>null</code> or empty, the attribute will be removed from the + * specified launch specification. + * + * @param launchSpec The launch specification. Must not be <code>null</code>. + * @param contexts The launch contexts to save or <code>null</code>. + */ + public final static void setLaunchContexts(ILaunchSpecification launchSpec, IStepContext[] contexts) { + Assert.isNotNull(launchSpec); + + if (contexts == null || contexts.length == 0) { + launchSpec.removeAttribute(IContextSelectorLaunchAttributes.ATTR_LAUNCH_CONTEXTS); + return; + } + + // Get the encoded XML representation + String xml = encodeLaunchContexts(contexts); + // And save them to the launch specification. If XML == null, the + // launch contexts will be removed from the launch specification + launchSpec.addAttribute(IContextSelectorLaunchAttributes.ATTR_LAUNCH_CONTEXTS, xml); + } + + /** + * Writes the given launch contexts into a string encoded in XML. + * + * @param contexts The launch contexts to encode. Must not be <code>null</code>. + * @return The full XML representation of the given contexts or <code>null</code>. + */ + public final static String encodeLaunchContexts(IStepContext[] contexts) { + Assert.isNotNull(contexts); + + // The final result + String result = null; + + // Generate the write cache key + String writeCacheKey = makeWriteCacheKey(contexts); + + // Check if we have the contexts already generated before + synchronized (writeCache) { + if (writeCache.containsKey(writeCacheKey)) { + result = writeCache.get(writeCacheKey); + } + } + + // If no cache hit, generate from scratch + if (result == null) { + // First, we write the selected contexts as XML representation into a string + StringWriter writer = new StringWriter(); + + try { + // Write the header and get the initial indentation + String indentation = writeHeader(writer); + // Iterate over the given selected step contexts and write them out. + for (IStepContext node : contexts) { + writeStepContext(writer, indentation, node); + } + // Write the footer + writeFooter(writer); + + // Convert into a string + result = writer.toString(); + + synchronized (writeCache) { + // Limit the write cache capacity + checkCacheCapacity(writeCache, WRITE_CACHE_MAX_CAPACITY); + // And put it into the write cache + writeCache.put(writeCacheKey, result); + } + } + catch (IOException e) { + // Export to the string writer failed --> remove attribute from launch configuration + if (CoreBundleActivator.getTraceHandler().getDebugMode() > 0) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + "Launch framework internal error: " + e.getLocalizedMessage(), e); //$NON-NLS-1$ + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + result = null; + } + finally { + try { + writer.close(); + } + catch (IOException e) { /* ignored on purpose */ + } + } + } + + return result; + } + + /** + * Generates a write cache key from the given contexts. + * + * @param contexts The contexts + * @return The corresponding write key cache. + */ + private static String makeWriteCacheKey(IStepContext[] contexts) { + Assert.isNotNull(contexts); + + StringBuffer key = new StringBuffer(); + for (IStepContext context : contexts) { + key.append(Integer.toHexString(context.hashCode())); + key.append(':'); + } + if (key.charAt(key.length() - 1) == ':') { + key.setCharAt(key.length() - 1, ' '); + } + return key.toString().trim(); + } + + /** + * Writes the header to the given writer and returns the indentation to be used for following + * elements. + * + * @param writer The writer instance. Must not be <code>null</code>. + * @throws IOException in case the write failed. + */ + private static String writeHeader(Writer writer) throws IOException { + Assert.isNotNull(writer); + writer.write("<contexts>\n"); //$NON-NLS-1$ + return "\t"; //$NON-NLS-1$ + } + + /** + * Writes the footer to the given writer and returns the indentation to be used for following + * elements. + * + * @param writer The writer instance. Must not be <code>null</code>. + * @throws IOException in case the write failed. + */ + private static String writeFooter(Writer writer) throws IOException { + Assert.isNotNull(writer); + writer.write("</contexts>\n"); //$NON-NLS-1$ + return ""; //$NON-NLS-1$ + } + + /** + * Writes the step context element to the given writer. + * + * @param writer The writer instance. Must not be <code>null</code>. + * @param indentation The indentation to prefix each exported line with. Must not be <code>null</code>. + * @param context The step context instance. Must not be <code>null</code>. + * + * @throws IOException in case the write failed. + */ + private static void writeStepContext(Writer writer, String indentation, IStepContext context) throws IOException { + Assert.isNotNull(writer); + Assert.isNotNull(indentation); + Assert.isNotNull(context); + + writer.write(indentation + "<context type=\"" + context.getModelNode().getClass().getName() + "\">\n"); //$NON-NLS-1$ //$NON-NLS-2$ + writer.write(indentation + "\t" + context.encode() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + writer.write(indentation + "</context>\n"); //$NON-NLS-1$ + } + + /** + * Reads the selected launch contexts from the given XML encoded string. + * + * @param encodedContexts The selected launch contexts encoded as XML string. Must not be <code>null</code>. + * @return The selected launch contexts or an empty array. + */ + public final static IStepContext[] decodeLaunchContexts(String encodedContexts) { + Assert.isNotNull(encodedContexts); + + List<IStepContext> contexts = null; + + if (!"".equals(encodedContexts.trim())) { //$NON-NLS-1$ + synchronized (readCache) { + // Check if we have the contexts already parsed before + if (readCache.containsKey(encodedContexts)) { + // Take the result from the cache + contexts = readCache.get(encodedContexts); + // check sanity. If empty or we cannot find the step context, + // drop the cache value and decode again. + ListIterator<IStepContext> iterator = contexts.listIterator(); + while (iterator.hasNext()) { + IStepContext node = iterator.next(); + if (!node.exists()) { + contexts = null; + readCache.remove(encodedContexts); + break; + } + } + + if (contexts != null && contexts.isEmpty()) { + readCache.remove(encodedContexts); + contexts = null; + } + } + } + + if (contexts == null || contexts.isEmpty()) { + contexts = new ArrayList<IStepContext>(); + // We have to parse the contexts from the string + InputStream input = new ByteArrayInputStream(encodedContexts.getBytes()); + // Instantiate the XML parser + LaunchContextXMLParser xmlParser = new LaunchContextXMLParser(); + xmlParser.initXMLParser(); + xmlParser.setContexts(contexts); + try { + xmlParser.getXMLReader().parse(input, xmlParser); + if (!contexts.isEmpty()) { + synchronized (readCache) { + // Limit the read cache capacity + checkCacheCapacity(readCache, READ_CACHE_MAX_CAPACITY); + // Put the result into the read cache + readCache.put(encodedContexts, contexts); + } + } + } + catch (Exception e) { + // Import failed --> remove attribute from launch configuration + if (CoreBundleActivator.getTraceHandler().getDebugMode() > 0) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + "Launch framework internal error: " + e.getLocalizedMessage(), e); //$NON-NLS-1$ + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + contexts = null; + } + } + } + + return contexts != null ? contexts.toArray(new IStepContext[contexts.size()]) : new IStepContext[0]; + } + + /** + * Internal helper method to ensure a maximum capacity of the caches. + */ + private final static void checkCacheCapacity(Map<String, ?> cache, int maxCapacity) { + if (cache.size() < maxCapacity) { + return; + } + // Get all keys + String[] keys = cache.keySet().toArray(new String[cache.keySet().size()]); + // And remove all keys starting with the eldest till the + // capacity is fine again. + for (String key : keys) { + cache.remove(key); + if (cache.size() < maxCapacity / 2) { + break; + } + } + } + + private final static class LaunchContextXMLParser extends DefaultHandler { + private final int IN_CONTEXTS_DEFINITION = 1; + private final int IN_CONTEXT_DEFINITION = 2; + + private SAXParser parser; + + private int parseState; + private String lastData; + private String lastType; + private List<IStepContext> contexts; + + /** + * Constructor + */ + public LaunchContextXMLParser() { + super(); + + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(false); + factory.setValidating(false); + try { + parser = factory.newSAXParser(); + } + catch (ParserConfigurationException e) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), e.getClass().getName(), e); + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + catch (SAXException e) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), e.getClass().getName(), e); + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + } + + /** + * Returns the associated XML parser instance. + */ + protected SAXParser getXMLReader() { + return parser; + } + + /** + * Reset the XML parser to a defined start point. + */ + protected void initXMLParser() { + parseState = 0; + lastData = null; + lastType = null; + contexts = null; + } + + /** + * Associate the list instance to store the identified contexts. + */ + protected void setContexts(List<IStepContext> contexts) { + this.contexts = contexts; + } + + /* + * (non-Javadoc) + * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, + * java.lang.String) + */ + @Override + public void endElement(String uri, String localName, String name) throws SAXException { + if ("contexts".equalsIgnoreCase(name) && (parseState & IN_CONTEXTS_DEFINITION) == IN_CONTEXTS_DEFINITION) { //$NON-NLS-1$ + parseState ^= IN_CONTEXTS_DEFINITION; + } + if ("context".equalsIgnoreCase(name) && (parseState & IN_CONTEXT_DEFINITION) == IN_CONTEXT_DEFINITION) { //$NON-NLS-1$ + parseState ^= IN_CONTEXT_DEFINITION; + + // The context encoded string is in last data + if (lastType != null && lastData != null) { + Class<IModelNode> clazz = null; + try { + clazz = (Class<IModelNode>)CoreBundleActivator.getContext().getBundle().loadClass(lastType); + } catch (ClassNotFoundException e) { + if (CoreBundleActivator.getTraceHandler().getDebugMode() > 0) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + "Launch framework internal error: " + e.getLocalizedMessage(), e); //$NON-NLS-1$ + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + } + + // If the class could not be loaded by our own bundle class loader, try to find + // the bundle from the class name and try to load the class through the bundle. + if (clazz == null) { + String bundleId = lastType; + Bundle bundle = null; + while (bundleId != null && bundle == null) { + bundle = Platform.getBundle(bundleId); + if (bundle == null) { + int i = bundleId.lastIndexOf('.'); + if (i != -1) { + bundleId = bundleId.substring(0, i); + } else { + bundleId = null; + } + } + } + + if (bundle != null) { + try { + clazz = (Class<IModelNode>)bundle.loadClass(lastType); + } catch (ClassNotFoundException e) { + if (CoreBundleActivator.getTraceHandler().getDebugMode() > 0) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + "Launch framework internal error: " + e.getLocalizedMessage(), e); //$NON-NLS-1$ + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + } + } + } + + if (clazz != null) { + // Try to load the step context + IStepContext context = (IStepContext)Platform.getAdapterManager().loadAdapter(clazz, IStepContext.class.getName()); + if (context != null && !contexts.contains(context)) { + contexts.add(context); + } + } + } + } + } + + /* (non-Javadoc) + * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) + */ + @Override + public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { + // Each time we start a new element, throw away the lastData content + lastData = null; + + if ("contexts".equalsIgnoreCase(name)) { //$NON-NLS-1$ + parseState |= IN_CONTEXTS_DEFINITION; + } + if ("context".equalsIgnoreCase(name) && (parseState & IN_CONTEXTS_DEFINITION) == IN_CONTEXTS_DEFINITION) { //$NON-NLS-1$ + parseState |= IN_CONTEXT_DEFINITION; + lastType = attributes.getValue("type"); //$NON-NLS-1$ + } + } + + /* (non-Javadoc) + * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int) + */ + @Override + public void characters(char ch[], int start, int length) { + if (lastData == null) { + lastData = new String(ch, start, length).trim(); + } + else { + lastData += new String(ch, start, length).trim(); + } + } + } + + /** + * Returns the list of configured launch contexts from the given launch configuration. + * <p> + * If the given launch configuration is <code>null</code> and the method will return an empty + * array. + * + * @param configuration The launch configuration or <code>null</code>. + * @return The list of configured launch contexts or an empty array. + */ + public static final IStepContext[] getLaunchContexts(ILaunchConfiguration configuration) { + IStepContext[] contexts = new IStepContext[0]; + + // First read the contexts written by the launch context selector control. + if (configuration != null) { + // Read the context attribute from the launch configuration + String encodedContexts = DefaultPersistenceDelegate.getAttribute(configuration, IContextSelectorLaunchAttributes.ATTR_LAUNCH_CONTEXTS, (String) null); + if (encodedContexts != null) { + contexts = ContextSelectorPersistenceDelegate.decodeLaunchContexts(encodedContexts); + } + } + + return contexts; + } + + /** + * Returns the list of configured launch contexts from the given launch specification. + * <p> + * If the given launch specification is <code>null</code> and the method will return an empty + * array. + * + * @param launchSpec The launch specification or <code>null</code>. + * @return The list of configured launch contexts or an empty array. + */ + public static final IStepContext[] getLaunchContexts(ILaunchSpecification launchSpec) { + IStepContext[] contexts = new IStepContext[0]; + + // First read the contexts written by the launch context selector control. + if (launchSpec != null) { + // Read the context attribute from the launch specification + String encodedContexts = (String) launchSpec.getAttribute(IContextSelectorLaunchAttributes.ATTR_LAUNCH_CONTEXTS, null); + if (encodedContexts != null) { + contexts = ContextSelectorPersistenceDelegate.decodeLaunchContexts(encodedContexts); + } + } + + return contexts; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/tabs/selector/ContextSelectorControl.java b/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/tabs/selector/ContextSelectorControl.java index 2bb37b79b..2dad81dea 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/tabs/selector/ContextSelectorControl.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/tabs/selector/ContextSelectorControl.java @@ -377,8 +377,12 @@ public class ContextSelectorControl extends BaseDialogPageControl implements ISe // checked, drop the model node and the use the container node only. if (element instanceof IModelNode) { IModelNode node = (IModelNode) element; - if (node.getParent() != null && checked.contains(node.getParent()) - && !grayed.contains(node.getParent())) { + + // Determine the parent node + IPropertiesAccessService service = ServiceManager.getInstance().getService(node, IPropertiesAccessService.class); + IModelNode parent = service != null ? (IModelNode)service.getParent(node) : node.getParent(); + + if (parent != null && checked.contains(parent) && !grayed.contains(parent)) { continue; } } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/tabs/selector/ContextSelectorSection.java b/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/tabs/selector/ContextSelectorSection.java index 85fee43ec..721555d85 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/tabs/selector/ContextSelectorSection.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/tabs/selector/ContextSelectorSection.java @@ -9,7 +9,11 @@ *******************************************************************************/
package org.eclipse.tcf.te.launch.ui.tabs.selector;
+import java.util.ArrayList;
+import java.util.List;
+
import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jface.action.Action;
@@ -18,10 +22,13 @@ import org.eclipse.jface.action.ToolBarManager; import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.tcf.te.launch.core.persistence.ContextSelectorPersistenceDelegate;
import org.eclipse.tcf.te.launch.ui.activator.UIPlugin;
import org.eclipse.tcf.te.launch.ui.interfaces.ILaunchConfigurationTabFormPart;
import org.eclipse.tcf.te.launch.ui.internal.ImageConsts;
import org.eclipse.tcf.te.launch.ui.nls.Messages;
+import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode;
+import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext;
import org.eclipse.tcf.te.ui.forms.parts.AbstractSection;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
@@ -94,7 +101,15 @@ public class ContextSelectorSection extends AbstractSection implements ILaunchCo createSectionToolbar(section, toolkit);
// Create the section sub controls
- selector = new StepContextSelectorControl(null);
+ selector = new StepContextSelectorControl(null) {
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.launch.ui.tabs.selector.StepContextSelectorControl#onModelNodeCheckStateChanged(org.eclipse.tcf.te.runtime.model.interfaces.IModelNode, boolean)
+ */
+ @Override
+ protected void onModelNodeCheckStateChanged(IModelNode node, boolean checked) {
+ getManagedForm().dirtyStateChanged();
+ }
+ };
selector.setFormToolkit(toolkit);
selector.setupPanel(client);
}
@@ -122,6 +137,24 @@ public class ContextSelectorSection extends AbstractSection implements ILaunchCo */
@Override
public void initializeFrom(ILaunchConfiguration configuration) {
+ Assert.isNotNull(configuration);
+
+ if (selector != null) {
+ IStepContext[] contexts = ContextSelectorPersistenceDelegate.getLaunchContexts(configuration);
+ if (contexts != null && contexts.length > 0) {
+ // Loop the contexts and create a list of nodes
+ List<IModelNode> nodes = new ArrayList<IModelNode>();
+ for (IStepContext context : contexts) {
+ IModelNode node = context.getModelNode();
+ if (node != null && !nodes.contains(node)) {
+ nodes.add(node);
+ }
+ }
+ if (!nodes.isEmpty()) {
+ selector.setCheckedModelContexts(nodes.toArray(new IModelNode[nodes.size()]));
+ }
+ }
+ }
}
/* (non-Javadoc)
@@ -129,6 +162,28 @@ public class ContextSelectorSection extends AbstractSection implements ILaunchCo */
@Override
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ Assert.isNotNull(configuration);
+
+ if (selector != null) {
+ IModelNode[] nodes = selector.getCheckedModelContexts();
+ // Loop the nodes and create a list of step contexts
+ List<IStepContext> contexts = new ArrayList<IStepContext>();
+ for (IModelNode node : nodes) {
+ IStepContext context = (IStepContext)Platform.getAdapterManager().loadAdapter(node, IStepContext.class.getName());
+ if (context != null && !contexts.contains(context)) {
+ contexts.add(context);
+ }
+ }
+
+ // Write the selected contexts to the launch configuration
+ if (!contexts.isEmpty()) {
+ ContextSelectorPersistenceDelegate.setLaunchContexts(configuration, contexts.toArray(new IStepContext[contexts.size()]));
+ } else {
+ ContextSelectorPersistenceDelegate.setLaunchContexts(configuration, null);
+ }
+ } else {
+ ContextSelectorPersistenceDelegate.setLaunchContexts(configuration, null);
+ }
}
/* (non-Javadoc)
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/factory/AbstractFactoryDelegate2.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/factory/AbstractFactoryDelegate2.java new file mode 100644 index 000000000..410afb33f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/factory/AbstractFactoryDelegate2.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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.model.factory;
+
+import org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactoryDelegate2;
+
+
+/**
+ * Abstract model node factory delegate implementing {@link IFactoryDelegate2}.
+ */
+public abstract class AbstractFactoryDelegate2 extends AbstractFactoryDelegate implements IFactoryDelegate2 {
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/factory/Factory.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/factory/Factory.java index b4c47aad7..926b9129a 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/factory/Factory.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/factory/Factory.java @@ -14,6 +14,7 @@ import org.eclipse.core.runtime.PlatformObject; import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode;
import org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactory;
import org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactoryDelegate;
+import org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactoryDelegate2;
import org.eclipse.tcf.te.runtime.model.internal.factory.FactoryDelegateManager;
/**
@@ -43,13 +44,8 @@ public final class Factory extends PlatformObject implements IFactory { super();
}
- /**
- * Creates an new instance of the model node object implementing
- * the specified node interface.
- *
- * @param nodeInterface The node interface to be implemented by the model node object to create.
- * Must not be <code>null</code>.
- * @return The model not object implementing the specified node interface or <code>null</code>.
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactory#newInstance(java.lang.Class)
*/
@Override
public <V extends IModelNode> V newInstance(Class<V> nodeInterface) {
@@ -58,6 +54,19 @@ public final class Factory extends PlatformObject implements IFactory { // Determine the model node factory delegate to use
IFactoryDelegate delegate = manager.getFactoryDelegate(nodeInterface);
// Return the model node instance
- return delegate != null ? (V)delegate.newInstance(nodeInterface) : null;
+ return delegate != null ? (V) delegate.newInstance(nodeInterface) : null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactory#newInstance(java.lang.Class, java.lang.Object[])
+ */
+ @Override
+ public <V extends IModelNode> V newInstance(Class<V> nodeInterface, Object[] args) {
+ Assert.isNotNull(nodeInterface);
+
+ // Determine the model node factory delegate to use
+ IFactoryDelegate delegate = manager.getFactoryDelegate(nodeInterface);
+ // Return the model node instance
+ return delegate instanceof IFactoryDelegate2 ? (V) ((IFactoryDelegate2)delegate).newInstance(nodeInterface, args) : null;
}
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/interfaces/factory/IFactory.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/interfaces/factory/IFactory.java index 0c1b5b407..176023481 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/interfaces/factory/IFactory.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/interfaces/factory/IFactory.java @@ -25,4 +25,20 @@ public interface IFactory extends IAdaptable { * @return The node object implementing the specified node interface or <code>null</code>.
*/
public <V extends IModelNode> V newInstance(Class<V> nodeInterface);
+
+ /**
+ * Creates an new instance of an node object implementing the specified node interface.
+ * <p>
+ * <b>Note:</b> Factory delegates must implement {@link IFactoryDelegate2} to be invoked by
+ * this method.
+ *
+ * @param nodeInterface The node interface to be implemented by the node object to be created.
+ * Must not be <code>null</code>.
+ * @param args The arguments to be passed to a matching constructor, or <code>null</code>.
+ *
+ * @return The node object implementing the specified node interface or <code>null</code>.
+ *
+ * @see IFactoryDelegate2#newInstance(Class, Object[])
+ */
+ public <V extends IModelNode> V newInstance(Class<V> nodeInterface, Object[] args);
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/interfaces/factory/IFactoryDelegate2.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/interfaces/factory/IFactoryDelegate2.java new file mode 100644 index 000000000..6b3f6cc72 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.model/src/org/eclipse/tcf/te/runtime/model/interfaces/factory/IFactoryDelegate2.java @@ -0,0 +1,37 @@ +/*******************************************************************************
+ * Copyright (c) 2012 Wind River Systems, Inc. and others. All rights reserved.
+ * This program and the accompanying materials are made available under the terms
+ * of the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.runtime.model.interfaces.factory;
+
+import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode;
+
+/**
+ * Interface to be implemented by model node factory delegates.
+ */
+public interface IFactoryDelegate2 extends IFactoryDelegate {
+
+ /**
+ * Returns a new instance of an node object implementing the given node interface.
+ * <p>
+ * If <code>args</code> is <code>null</code>, the node object returned by this method
+ * should be the same as by calling {@link #newInstance(Class)}.
+ * <p>
+ * If <code>args</code> is not <code>null</code>, the method is matching the argument
+ * types with the argument types of the node object constructor(s) and call the matched
+ * constructor. If no constructor is matching the argument types, the method does return
+ * <code>null</code>.
+ *
+ * @param nodeInterface The node interface to be implemented by the node object to be created.
+ * Must not be <code>null</code>.
+ * @param args The arguments to be passed to a matching constructor, or <code>null</code>.
+ *
+ * @return The node object implementing the specified node interface or <code>null</code>.
+ */
+ public <V extends IModelNode> V newInstance(Class<V> nodeInterface, Object[] args);
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/interfaces/IPropertiesAccessService.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/interfaces/IPropertiesAccessService.java index 29b1de9bc..f26b29b67 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/interfaces/IPropertiesAccessService.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/interfaces/IPropertiesAccessService.java @@ -14,8 +14,8 @@ import java.util.Map; /**
* Properties access service.
* <p>
- * Allows generic access to properties of a given context without having
- * to know all the details and limitations for accessing the desired properties.
+ * Allows generic access to properties of a given context without having to know all the details and
+ * limitations for accessing the desired properties.
*/
public interface IPropertiesAccessService extends IService {
@@ -40,8 +40,8 @@ public interface IPropertiesAccessService extends IService { public Map<String, String> getTargetAddress(Object context);
/**
- * Returns the property value stored under the given property key. If the property
- * does not exist, <code>null</code> is returned.
+ * Returns the property value stored under the given property key. If the property does not
+ * exist, <code>null</code> is returned.
*
* @param context The context to get the property from. Must not be <code>null</code>.
* @param key The property key. Must not be <code>null</code>.
@@ -49,4 +49,12 @@ public interface IPropertiesAccessService extends IService { * @return The stored property value or <code>null</code>.
*/
public Object getProperty(Object context, String key);
+
+ /**
+ * Returns the direct parent node of the given context object.
+ *
+ * @param context The context to get the parent from. Must not be <code>null</code>.
+ * @return The direct parent node or <code>null</code>.
+ */
+ public Object getParent(Object context);
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStepContext.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStepContext.java index fb8b1a712..082d9ff23 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStepContext.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.stepper/src/org/eclipse/tcf/te/runtime/stepper/interfaces/IStepContext.java @@ -40,4 +40,28 @@ public interface IStepContext extends IModelNodeProvider { * @return The context information or <code>null</code>.
*/
public String getInfo(IPropertiesContainer data);
+
+ /**
+ * Returns if or if not the associated model node really exist.
+ *
+ * @return <code>True</code> if the associated model node really exists, <code>false</code> otherwise.
+ */
+ public boolean exists();
+
+ /**
+ * Encodes the context to an persistable representation.
+ * <p>
+ * <b>Note:</b> The persistable representation is expected to be a single line.
+ *
+ * @return The persistable representation of the context.
+ */
+ public String encode();
+
+ /**
+ * Decodes the given persistable representation and store the result
+ * in the context.
+ *
+ * @param value The persistable representation of the context. Must not be <code>null</code>.
+ */
+ public void decode(String value);
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/tracing/TraceHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/tracing/TraceHandler.java index 12e1df46e..354c60a49 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/tracing/TraceHandler.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/tracing/TraceHandler.java @@ -194,7 +194,7 @@ public class TraceHandler { /**
* Returns the tracer instance. Create a new tracer instance
- * on first invokation.
+ * on first invocation.
*
* @return The tracer instance.
*/
@@ -206,6 +206,13 @@ public class TraceHandler { }
/**
+ * Return the current debug mode.
+ */
+ public final int getDebugMode() {
+ return getTracer().getDebugMode();
+ }
+
+ /**
* Check whether a trace slot is enabled with the given debug mode.
*
* @param debugMode The debug mode
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/internal/adapters/AdapterFactory.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/internal/adapters/AdapterFactory.java index 0b7c00eda..e375bd046 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/internal/adapters/AdapterFactory.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/internal/adapters/AdapterFactory.java @@ -13,8 +13,10 @@ import java.util.HashMap; import java.util.Map;
import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.te.runtime.interfaces.IDisposable;
import org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IModelListener;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
import org.eclipse.tcf.te.tcf.locator.listener.ModelAdapter;
@@ -35,7 +37,7 @@ public class AdapterFactory implements IAdapterFactory { * Constructor.
*/
public AdapterFactory() {
- Model.getModel().addListener(new ModelAdapter() {
+ final IModelListener listener = new ModelAdapter() {
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.locator.listener.ModelAdapter#locatorModelChanged(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel, org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel, boolean)
*/
@@ -47,7 +49,17 @@ public class AdapterFactory implements IAdapterFactory { if (adapter instanceof IDisposable) ((IDisposable)adapter).dispose();
}
}
- });
+ };
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ Model.getModel().addListener(listener);
+ }
+ };
+
+ if (Protocol.isDispatchThread()) runnable.run();
+ else Protocol.invokeAndWait(runnable);
}
/* (non-Javadoc)
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/internal/adapters/StepContextAdapter.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/internal/adapters/StepContextAdapter.java index 5b701e0e0..963e9afa1 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/internal/adapters/StepContextAdapter.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/internal/adapters/StepContextAdapter.java @@ -9,10 +9,15 @@ *******************************************************************************/
package org.eclipse.tcf.te.tcf.launch.core.internal.adapters;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.tcf.protocol.JSON;
import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode;
@@ -24,7 +29,7 @@ import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel; */
public class StepContextAdapter extends PlatformObject implements IStepContext {
// Reference to the wrapped peer model
- /* default */ final IPeerModel peerModel;
+ /* default */ IPeerModel peerModel;
/**
* Constructor.
@@ -50,7 +55,7 @@ public class StepContextAdapter extends PlatformObject implements IStepContext { */
@Override
public String getId() {
- return peerModel.getPeerId();
+ return peerModel != null ? peerModel.getPeerId() : null;
}
/* (non-Javadoc)
@@ -60,25 +65,89 @@ public class StepContextAdapter extends PlatformObject implements IStepContext { public String getName() {
final AtomicReference<String> name = new AtomicReference<String>();
+ if (peerModel != null) {
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ name.set(peerModel.getName());
+ }
+ };
+
+ if (Protocol.isDispatchThread()) runnable.run();
+ else Protocol.invokeAndWait(runnable);
+ }
+
+ return name.get();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext#getInfo(org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer)
+ */
+ @Override
+ public String getInfo(IPropertiesContainer data) {
+ return ""; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext#exists()
+ */
+ @Override
+ public boolean exists() {
+ final AtomicBoolean isGhost = new AtomicBoolean();
+
+ if (peerModel != null) {
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ isGhost.set(peerModel.getBooleanProperty(IModelNode.PROPERTY_IS_GHOST));
+ }
+ };
+
+ if (Protocol.isDispatchThread()) runnable.run();
+ else Protocol.invokeAndWait(runnable);
+ }
+
+ return peerModel != null && !isGhost.get();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext#encode()
+ */
+ @Override
+ public String encode() {
+ final AtomicReference<String> encoded = new AtomicReference<String>();
+
Runnable runnable = new Runnable() {
@Override
public void run() {
- name.set(peerModel.getName());
+ try {
+ Map<String, String> attrs = new HashMap<String, String>(peerModel.getPeer().getAttributes());
+
+ // Remove all transient attributes
+ String[] keys = attrs.keySet().toArray(new String[attrs.keySet().size()]);
+ for (String key : keys) {
+ if (key.endsWith(".transient")) { //$NON-NLS-1$
+ attrs.remove(key);
+ }
+ }
+
+ encoded.set(JSON.toJSON(attrs));
+ }
+ catch (IOException e) { /* ignored on purpose */ }
}
};
if (Protocol.isDispatchThread()) runnable.run();
else Protocol.invokeAndWait(runnable);
- return name.get();
+ return encoded.get() != null ? encoded.get() : ""; //$NON-NLS-1$
}
/* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext#getInfo(org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer)
+ * @see org.eclipse.tcf.te.runtime.stepper.interfaces.IStepContext#decode(java.lang.String)
*/
@Override
- public String getInfo(IPropertiesContainer data) {
- return ""; //$NON-NLS-1$
+ public void decode(String value) {
+ Assert.isNotNull(value);
}
-
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.xml b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.xml index 525a72695..7e16fab85 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.xml +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/plugin.xml @@ -56,4 +56,13 @@ </service> </extension> +<!-- Model node factory delegate contributions --> + <extension point="org.eclipse.tcf.te.runtime.model.factoryDelegates"> + <delegate + class="org.eclipse.tcf.te.tcf.locator.internal.ModelNodeFactoryDelegate" + id="org.eclipse.tcf.te.tcf.locator.model.factory.delegate"> + <nodeType class="org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel"/> + </delegate> + </extension> + </plugin> diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/ModelNodeFactoryDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/ModelNodeFactoryDelegate.java new file mode 100644 index 000000000..b60c862ec --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/ModelNodeFactoryDelegate.java @@ -0,0 +1,47 @@ +/*******************************************************************************
+ * Copyright (c) 2012 Wind River Systems, Inc. and others. All rights reserved.
+ * This program and the accompanying materials are made available under the terms
+ * of the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.tcf.locator.internal;
+
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.te.runtime.model.factory.AbstractFactoryDelegate2;
+import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.nodes.PeerModel;
+
+/**
+ * Locator model node factory delegate implementation.
+ */
+public class ModelNodeFactoryDelegate extends AbstractFactoryDelegate2 {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactoryDelegate#newInstance(java.lang.Class)
+ */
+ @Override
+ public <V extends IModelNode> V newInstance(Class<V> nodeInterface) {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactoryDelegate2#newInstance(java.lang.Class, java.lang.Object[])
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public <V extends IModelNode> V newInstance(Class<V> nodeInterface, Object[] args) {
+ if (IPeerModel.class.equals(nodeInterface)) {
+ // Peer model constructor has 2 arguments, ILocatorModel and IPeer
+ if (args.length == 2 && args[0] instanceof ILocatorModel && args[1] instanceof IPeer) {
+ return (V) new PeerModel((ILocatorModel)args[0], (IPeer)args[1]);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/services/PropertiesAccessService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/services/PropertiesAccessService.java index 3ed95ee12..e8a96f61c 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/services/PropertiesAccessService.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/internal/services/PropertiesAccessService.java @@ -92,4 +92,28 @@ public class PropertiesAccessService extends AbstractService implements IPropert return value.get();
}
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.services.interfaces.IPropertiesAccessService#getParent(java.lang.Object)
+ */
+ @Override
+ public Object getParent(final Object context) {
+ Assert.isNotNull(context);
+
+ final AtomicReference<Object> value = new AtomicReference<Object>();
+ if (context instanceof IPeerModel) {
+ final IPeerModel peerModel = (IPeerModel) context;
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ value.set(peerModel.getParent());
+ }
+ };
+
+ if (Protocol.isDispatchThread()) runnable.run();
+ else Protocol.invokeAndWait(runnable);
+ }
+
+ return value.get();
+ }
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/PeerModel.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/PeerModel.java index 75c6d362a..d7df59572 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/PeerModel.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/nodes/PeerModel.java @@ -35,7 +35,7 @@ public class PeerModel extends ContainerModelNode implements IPeerModel, IWorkin * Constructor. * * @param model The parent locator model. Must not be <code>null</code>. - * @param peer The peer or <code>null</code>. + * @param peer The peer. Must not be <code>null</code>. */ public PeerModel(ILocatorModel model, IPeer peer) { super(); @@ -43,6 +43,8 @@ public class PeerModel extends ContainerModelNode implements IPeerModel, IWorkin Assert.isNotNull(model); this.model = model; + Assert.isNotNull(peer); + // Set the default properties before enabling the change events. // The properties changed listeners should not be called from the // constructor. diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.services.contexts/src/org/eclipse/tcf/te/tcf/services/contexts/internal/AdapterFactory.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.services.contexts/src/org/eclipse/tcf/te/tcf/services/contexts/internal/AdapterFactory.java index b6f8770d3..d0e1ac86e 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.services.contexts/src/org/eclipse/tcf/te/tcf/services/contexts/internal/AdapterFactory.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.services.contexts/src/org/eclipse/tcf/te/tcf/services/contexts/internal/AdapterFactory.java @@ -14,7 +14,9 @@ import java.util.Map; import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.te.runtime.interfaces.IDisposable;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IModelListener;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
import org.eclipse.tcf.te.tcf.locator.listener.ModelAdapter;
@@ -36,7 +38,7 @@ public class AdapterFactory implements IAdapterFactory { * Constructor.
*/
public AdapterFactory() {
- Model.getModel().addListener(new ModelAdapter() {
+ final IModelListener listener = new ModelAdapter() {
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.locator.listener.ModelAdapter#locatorModelChanged(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel, org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel, boolean)
*/
@@ -48,7 +50,17 @@ public class AdapterFactory implements IAdapterFactory { if (adapter instanceof IDisposable) ((IDisposable)adapter).dispose();
}
}
- });
+ };
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ Model.getModel().addListener(listener);
+ }
+ };
+
+ if (Protocol.isDispatchThread()) runnable.run();
+ else Protocol.invokeAndWait(runnable);
}
/* (non-Javadoc)
|