Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'target_explorer/plugins')
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/interfaces/IMenuService.java4
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/IChannelManager.java9
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/internal/ChannelManager.java46
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/va/AbstractExternalValueAdd.java5
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/ScannerRunnable.java11
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/LocatorListener.java68
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelPeerNodeQueryService.java518
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelRefreshService.java12
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelUpdateService.java30
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tests/src/org/eclipse/tcf/te/tests/tcf/TcfTestCase.java430
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.ui.views/src/org/eclipse/tcf/te/ui/views/ViewsUtil.java39
11 files changed, 683 insertions, 489 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/interfaces/IMenuService.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/interfaces/IMenuService.java
index 7b8da18c1..6fd9479f4 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/interfaces/IMenuService.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/interfaces/IMenuService.java
@@ -20,8 +20,8 @@ public interface IMenuService extends IService {
* Tests if or if not the menu contribution identified by the given id is
* visible for the given context.
*
- * @param context The context. Must be not <code>null</code>.
- * @param contributionID The contribution ID. Must be not <code>null</code>.
+ * @param context The context. Must not be <code>null</code>.
+ * @param contributionID The contribution ID. Must not be <code>null</code>.
*
* @return <code>True</code> if the contribution is visible, <code>false</code> otherwise.
*/
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/IChannelManager.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/IChannelManager.java
index b5e2b90db..85c8a4bbb 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/IChannelManager.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/IChannelManager.java
@@ -113,9 +113,18 @@ public interface IChannelManager extends IAdaptable {
public void closeChannel(IChannel channel);
/**
+ * Shutdown the communication to the given peer, no matter of the current
+ * reference count. A possible associated value-add is shutdown as well.
+ *
+ * @param peer The peer. Must not be <code>null</code>.
+ */
+ public void shutdown(IPeer peer);
+
+ /**
* Close all open channel, no matter of the current reference count.
* <p>
* The method can be called from any thread context.
*/
public void closeAll();
+
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/internal/ChannelManager.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/internal/ChannelManager.java
index 3274e1979..3d5e36d13 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/internal/ChannelManager.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/internal/ChannelManager.java
@@ -418,6 +418,52 @@ public final class ChannelManager extends PlatformObject implements IChannelMana
}
/* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager#shutdown(org.eclipse.tcf.protocol.IPeer)
+ */
+ @Override
+ public void shutdown(final IPeer peer) {
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ internalShutdown(peer);
+ }
+ };
+ if (Protocol.isDispatchThread()) runnable.run();
+ else Protocol.invokeLater(runnable);
+ }
+
+ /**
+ * Shutdown the communication to the given peer, no matter of the current
+ * reference count. A possible associated value-add is shutdown as well.
+ *
+ * @param peer The peer. Must not be <code>null</code>.
+ */
+ /* default */ void internalShutdown(IPeer peer) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(peer);
+
+ // Get the peer id
+ String id = peer.getID();
+
+ // Get the channel
+ IChannel channel = internalGetChannel(peer);
+ if (channel != null) {
+ // Reset the reference count (will force a channel close)
+ refCounters.remove(id);
+
+ // Close the channel
+ internalCloseChannel(channel);
+
+ // Get the value-add's for the peer to shutdown
+ IValueAdd[] valueAdds = ValueAddManager.getInstance().getValueAdd(peer);
+ if (valueAdds != null && valueAdds.length > 0) {
+ internalShutdownValueAdds(peer, valueAdds);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager#closeAll()
*/
@Override
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/va/AbstractExternalValueAdd.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/va/AbstractExternalValueAdd.java
index c4b88ba98..e4860fe63 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/va/AbstractExternalValueAdd.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/va/AbstractExternalValueAdd.java
@@ -232,7 +232,7 @@ public abstract class AbstractExternalValueAdd extends AbstractValueAdd {
// Find the "Server-Properties: ..." string within the output
int start = output.indexOf("Server-Properties:"); //$NON-NLS-1$
- if (start != -1) {
+ if (start != -1 && start > 0) {
output = output.substring(start);
}
@@ -275,6 +275,9 @@ public abstract class AbstractExternalValueAdd extends AbstractValueAdd {
entries.put(id, entry);
}
+
+ // Stop the output reader thread
+ launcher.getOutputReader().interrupt();
} else {
error = new FileNotFoundException(NLS.bind(Messages.AbstractExternalValueAdd_error_invalidLocation, this.getId()));
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/ScannerRunnable.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/ScannerRunnable.java
index ffe413c25..a2f7f1853 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/ScannerRunnable.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/ScannerRunnable.java
@@ -83,6 +83,11 @@ public class ScannerRunnable implements Runnable, IChannel.IChannelListener {
public void run() {
Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ // If a scanner runnable already active for this peer node, there
+ // is no need to run another scan.
+ if (peerNode.getProperty("scanner.transient") != null) return; //$NON-NLS-1$
+ peerNode.setProperty("scanner.transient", this); //$NON-NLS-1$
+
// Determine the peer
IPeer peer = peerNode.getPeer();
if (peer == null) return;
@@ -306,6 +311,9 @@ public class ScannerRunnable implements Runnable, IChannel.IChannelListener {
if (!sharedChannel && !keepOpen) channel.close();
}
+ // Reset the scanner runnable marker
+ peerNode.setProperty("scanner.transient", null); //$NON-NLS-1$
+
// Re-enable the change events a fire a "properties" change event
if (changed) {
peerNode.setChangeEventsEnabled(true);
@@ -350,6 +358,9 @@ public class ScannerRunnable implements Runnable, IChannel.IChannelListener {
peerNode.setProperty("dns.lastIP.transient", null); //$NON-NLS-1$
peerNode.setProperty("dns.skip.transient", null); //$NON-NLS-1$
+ // Reset the scanner runnable marker
+ peerNode.setProperty("scanner.transient", null); //$NON-NLS-1$
+
// Re-enable the change events a fire a "properties" change event
if (changed) {
peerNode.setChangeEventsEnabled(true);
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/LocatorListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/LocatorListener.java
index 1e53d377e..f2ac8a12a 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/LocatorListener.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/listener/LocatorListener.java
@@ -9,7 +9,9 @@
*******************************************************************************/
package org.eclipse.tcf.te.tcf.locator.listener;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -126,6 +128,13 @@ public class LocatorListener implements ILocator.LocatorListener {
if (model != null && peer != null) {
// find the corresponding model node to remove
IPeerModel peerNode = model.getService(ILocatorModelLookupService.class).lkupPeerModelById(peer.getID());
+ if (peerNode == null) {
+ // Double check with "ClientID" if set
+ String clientID = peer.getAttributes().get("ClientID"); //$NON-NLS-1$
+ if (clientID != null) {
+ peerNode = model.getService(ILocatorModelLookupService.class).lkupPeerModelById(clientID);
+ }
+ }
// Update the peer instance
if (peerNode != null) {
// Get the old peer instance
@@ -138,7 +147,15 @@ public class LocatorListener implements ILocator.LocatorListener {
}
// Non-visible peers are updated
else {
- model.getService(ILocatorModelUpdateService.class).mergeUserDefinedAttributes(peerNode, peer, false);
+ // Validate the peer node before updating
+ IPeer myPeer = model.validatePeer(peer);
+ if (myPeer != null) {
+ boolean changed = peerNode.setChangeEventsEnabled(false);
+ // Merge user configured properties between the peers
+ model.getService(ILocatorModelUpdateService.class).mergeUserDefinedAttributes(peerNode, myPeer, true);
+ if (changed) peerNode.setChangeEventsEnabled(true);
+ peerNode.fireChangeEvent(IPeerModelProperties.PROP_INSTANCE, myPeer, peerNode.getPeer());
+ }
}
}
}
@@ -167,19 +184,50 @@ public class LocatorListener implements ILocator.LocatorListener {
String value = peer.getAttributes().get("static.transient"); //$NON-NLS-1$
boolean isStatic = value != null && Boolean.parseBoolean(value.trim());
if (isStatic) {
+ boolean changed = peerNode.setChangeEventsEnabled(false);
+
// Create a modifiable copy of the peer attributes
Map<String, String> attrs = new HashMap<String, String>(peerNode.getPeer().getAttributes());
- attrs.remove("remote.transient"); //$NON-NLS-1$
- attrs.remove("remote.id.transient"); //$NON-NLS-1$
- attrs.remove("ClientID"); //$NON-NLS-1$
-
- // Update the peer attributes
- if (peer instanceof PeerRedirector) {
- ((PeerRedirector)peer).updateAttributes(attrs);
- } else if (peer instanceof Peer) {
- ((Peer)peer).updateAttributes(attrs);
+ // Remember the remote peer id before removing it
+ String remotePeerID = attrs.get("remote.id.transient"); //$NON-NLS-1$
+
+ // Remove all merged attributes from the peer instance
+ String merged = attrs.remove("remote.merged.transient"); //$NON-NLS-1$
+ if (merged != null) {
+ merged = merged.replace('[', ' ').replace(']', ' ').trim();
+ List<String> keysToRemove = Arrays.asList(merged.split(",\\ ")); //$NON-NLS-1$
+ String[] keys = attrs.keySet().toArray(new String[attrs.keySet().size()]);
+ for (String key : keys) {
+ if (keysToRemove.contains(key)) {
+ attrs.remove(key);
+ }
+ }
+
+ // Make sure the ID is set correctly
+ if (attrs.get(IPeer.ATTR_ID) == null) {
+ attrs.put(IPeer.ATTR_ID, peer.getID());
+ }
+
+ // Update the peer attributes
+ if (peer instanceof PeerRedirector) {
+ ((PeerRedirector)peer).updateAttributes(attrs);
+ } else if (peer instanceof Peer) {
+ ((Peer)peer).updateAttributes(attrs);
+ }
+ }
+
+ // Remove the attributes stored at peer node level
+ peerNode.setProperty(IPeerModelProperties.PROP_LOCAL_SERVICES, null);
+ peerNode.setProperty(IPeerModelProperties.PROP_REMOTE_SERVICES, null);
+
+ // Check if we have to remote the peer in the underlying locator service too
+ if (remotePeerID != null) {
+ Map<String, IPeer> peers = Protocol.getLocator().getPeers();
+ IPeer remotePeer = peers.get(remotePeerID);
+ if (remotePeer instanceof AbstractPeer) ((AbstractPeer)remotePeer).dispose();
}
+ if (changed) peerNode.setChangeEventsEnabled(true);
peerNode.fireChangeEvent(IPeerModelProperties.PROP_INSTANCE, peer, peerNode.getPeer());
} else {
// Dynamic peer -> Remove peer model node from the model
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelPeerNodeQueryService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelPeerNodeQueryService.java
index 02b9c7348..0f0e573f2 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelPeerNodeQueryService.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelPeerNodeQueryService.java
@@ -1,253 +1,265 @@
-/*******************************************************************************
- * 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.services;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-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.tcf.protocol.IChannel;
-import org.eclipse.tcf.protocol.Protocol;
-import org.eclipse.tcf.te.runtime.interfaces.IConditionTester;
-import org.eclipse.tcf.te.tcf.core.Tcf;
-import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager;
-import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
-import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
-import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties;
-import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelPeerNodeQueryService;
-import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService;
-
-/**
- * Default locator model peer node query service implementation.
- */
-public class LocatorModelPeerNodeQueryService extends AbstractLocatorModelService implements ILocatorModelPeerNodeQueryService {
-
- /**
- * Constructor.
- *
- * @param parentModel The parent locator model instance. Must not be <code>null</code>.
- */
- public LocatorModelPeerNodeQueryService(ILocatorModel parentModel) {
- super(parentModel);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelPeerNodeQueryService#queryLocalServices(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel)
- */
- @Override
- public String queryLocalServices(final IPeerModel node) {
- Assert.isTrue(!Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
- Assert.isNotNull(node);
-
- // Check if the services has been cached before
- final AtomicReference<String> services = new AtomicReference<String>();
- Protocol.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- services.set(node.getStringProperty(IPeerModelProperties.PROP_LOCAL_SERVICES));
- }
- });
-
- if (services.get() != null && !"".equals(services.get())) { //$NON-NLS-1$
- // Services are cached -> return immediately
- return services.get();
- }
-
- // Get the service asynchronously and block the caller thread until
- // the callback returned
- final AtomicBoolean completed = new AtomicBoolean(false);
- Protocol.invokeLater(new Runnable() {
- @Override
- public void run() {
- doQueryServices(node, new DoneQueryServices() {
- @Override
- public void doneQueryServices(Throwable error) {
- if (error == null) services.set(node.getStringProperty(IPeerModelProperties.PROP_LOCAL_SERVICES));
- completed.set(true);
- }
- });
- }
- });
-
- final long startTime = System.currentTimeMillis();
- final IConditionTester tester = new IConditionTester() {
- @Override
- public boolean isConditionFulfilled() {
- return completed.get();
- }
-
- @Override
- public void cleanup() {}
- };
-
- while ((startTime + 1000) < System.currentTimeMillis() && !tester.isConditionFulfilled()) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) { /* ignored on purpose */ }
- }
-
- return services.get();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelPeerNodeQueryService#queryRemoteServices(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel)
- */
- @Override
- public String queryRemoteServices(final IPeerModel node) {
- Assert.isTrue(!Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
- Assert.isNotNull(node);
-
- // Check if the services has been cached before
- final AtomicReference<String> services = new AtomicReference<String>();
- Protocol.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- services.set(node.getStringProperty(IPeerModelProperties.PROP_REMOTE_SERVICES));
- }
- });
-
- if (services.get() != null && !"".equals(services.get())) { //$NON-NLS-1$
- // Services are cached -> return immediately
- return services.get();
- }
-
- // Get the service asynchronously and block the caller thread until
- // the callback returned
- final AtomicBoolean completed = new AtomicBoolean(false);
- Protocol.invokeLater(new Runnable() {
- @Override
- public void run() {
- doQueryServices(node, new DoneQueryServices() {
- @Override
- public void doneQueryServices(Throwable error) {
- if (error == null) services.set(node.getStringProperty(IPeerModelProperties.PROP_REMOTE_SERVICES));
- completed.set(true);
- }
- });
- }
- });
-
- final long startTime = System.currentTimeMillis();
- final IConditionTester tester = new IConditionTester() {
- @Override
- public boolean isConditionFulfilled() {
- return completed.get();
- }
-
- @Override
- public void cleanup() {}
- };
-
- while ((startTime + 1000) < System.currentTimeMillis() && !tester.isConditionFulfilled()) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) { /* ignored on purpose */ }
- }
-
- return services.get();
- }
-
- /**
- * Client call back interface for doQueryServices(...).
- */
- /* default */ interface DoneQueryServices {
- /**
- * Called when the services query completed.
- *
- * @param error The error description if operation failed, <code>null</code> if succeeded.
- */
- void doneQueryServices(Throwable error);
- }
-
- /* default */ final Map<IPeerModel, List<DoneQueryServices>> serviceQueriesInProgress = new HashMap<IPeerModel, List<DoneQueryServices>>();
-
- /**
- * Opens a channel to the peer node and query the services from the opened channel.
- *
- * @param node The peer node. Must not be <code>null</code>.
- * @param serviceType The type of the requested services. See {@link IPeerModelProperties#PROP_LOCAL_SERVICES} and {@link IPeerModelProperties#PROP_REMOTE_SERVICES}.
- * @param done The client callback. Must not be <code>null</code>.
- */
- protected void doQueryServices(final IPeerModel node, final DoneQueryServices done) {
- Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
- Assert.isNotNull(node);
- Assert.isNotNull(done);
-
- // If a service query for the same peer is already in progress,
- // attach the new done to the list to call and drop out
- if (serviceQueriesInProgress.containsKey(node)) {
- List<DoneQueryServices> dones = serviceQueriesInProgress.get(node);
- Assert.isNotNull(dones);
- dones.add(done);
- return;
- }
-
- // Add the done callback to a list of waiting callbacks per peer node
- List<DoneQueryServices> dones = new ArrayList<DoneQueryServices>();
- dones.add(done);
- serviceQueriesInProgress.put(node, dones);
-
- // Create the inner callback that invokes the queued outer callbacks
- final DoneQueryServices innerDone = new DoneQueryServices() {
-
- @Override
- public void doneQueryServices(Throwable error) {
- // Get the list of the original done callbacks
- List<DoneQueryServices> dones = serviceQueriesInProgress.remove(node);
- for (DoneQueryServices done : dones) {
- done.doneQueryServices(error);
- }
- }
- };
-
- // Do not try to open a channel to peers known to be unreachable
- int state = node.getIntProperty(IPeerModelProperties.PROP_STATE);
- if (state == IPeerModelProperties.STATE_ERROR || state == IPeerModelProperties.STATE_NOT_REACHABLE || !node.isComplete()) {
- innerDone.doneQueryServices(null);
- return;
- }
-
- // Opens a channel with the full value-add chain
- Tcf.getChannelManager().openChannel(node.getPeer(), null, new IChannelManager.DoneOpenChannel() {
-
- @Override
- public void doneOpenChannel(Throwable error, IChannel channel) {
- // If the channel opening failed -> return immediately
- if (error != null) {
- innerDone.doneQueryServices(error);
- } else {
- // Get the local service
- List<String> localServices = new ArrayList<String>(channel.getLocalServices());
- // Get the remote services
- List<String> remoteServices = new ArrayList<String>(channel.getRemoteServices());
-
- // Close the channel
- Tcf.getChannelManager().closeChannel(channel);
-
- // Sort the service lists
- Collections.sort(localServices);
- Collections.sort(remoteServices);
-
- // Update the services
- ILocatorModelUpdateService updateService = node.getModel().getService(ILocatorModelUpdateService.class);
- updateService.updatePeerServices(node, localServices, remoteServices);
-
- // Invoke the callback
- innerDone.doneQueryServices(null);
- }
- }
- });
- }
-}
+/*******************************************************************************
+ * 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.services;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+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.tcf.protocol.IChannel;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.te.runtime.interfaces.IConditionTester;
+import org.eclipse.tcf.te.tcf.core.Tcf;
+import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelPeerNodeQueryService;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService;
+
+/**
+ * Default locator model peer node query service implementation.
+ */
+public class LocatorModelPeerNodeQueryService extends AbstractLocatorModelService implements ILocatorModelPeerNodeQueryService {
+
+ /**
+ * Constructor.
+ *
+ * @param parentModel The parent locator model instance. Must not be <code>null</code>.
+ */
+ public LocatorModelPeerNodeQueryService(ILocatorModel parentModel) {
+ super(parentModel);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelPeerNodeQueryService#queryLocalServices(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel)
+ */
+ @Override
+ public String queryLocalServices(final IPeerModel node) {
+ Assert.isTrue(!Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(node);
+
+ // Check if the services has been cached before
+ final AtomicReference<String> services = new AtomicReference<String>();
+ Protocol.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ services.set(node.getStringProperty(IPeerModelProperties.PROP_LOCAL_SERVICES));
+ }
+ });
+
+ if (services.get() != null && !"".equals(services.get())) { //$NON-NLS-1$
+ // Services are cached -> return immediately
+ return services.get();
+ }
+
+ // Get the service asynchronously and block the caller thread until
+ // the callback returned
+ final AtomicBoolean completed = new AtomicBoolean(false);
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ // If the peer is a RemotePeer or has the "remote.transient" property set
+ // --> an agent is running and has been associated with the peer model.
+ if ("RemotePeer".equals(node.getPeer().getClass().getSimpleName()) || Boolean.valueOf(node.getPeer().getAttributes().get("remote.transient")).booleanValue()) { //$NON-NLS-1$ //$NON-NLS-2$
+ doQueryServices(node, new DoneQueryServices() {
+ @Override
+ public void doneQueryServices(Throwable error) {
+ if (error == null) services.set(node.getStringProperty(IPeerModelProperties.PROP_LOCAL_SERVICES));
+ completed.set(true);
+ }
+ });
+ } else {
+ completed.set(true);
+ }
+ }
+ });
+
+ final long startTime = System.currentTimeMillis();
+ final IConditionTester tester = new IConditionTester() {
+ @Override
+ public boolean isConditionFulfilled() {
+ return completed.get();
+ }
+
+ @Override
+ public void cleanup() {}
+ };
+
+ while ((startTime + 1000) < System.currentTimeMillis() && !tester.isConditionFulfilled()) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) { /* ignored on purpose */ }
+ }
+
+ return services.get();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelPeerNodeQueryService#queryRemoteServices(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel)
+ */
+ @Override
+ public String queryRemoteServices(final IPeerModel node) {
+ Assert.isTrue(!Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(node);
+
+ // Check if the services has been cached before
+ final AtomicReference<String> services = new AtomicReference<String>();
+ Protocol.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ services.set(node.getStringProperty(IPeerModelProperties.PROP_REMOTE_SERVICES));
+ }
+ });
+
+ if (services.get() != null && !"".equals(services.get())) { //$NON-NLS-1$
+ // Services are cached -> return immediately
+ return services.get();
+ }
+
+ // Get the service asynchronously and block the caller thread until
+ // the callback returned
+ final AtomicBoolean completed = new AtomicBoolean(false);
+ Protocol.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ // If the peer is a RemotePeer or has the "remote.transient" property set
+ // --> an agent is running and has been associated with the peer model.
+ if ("RemotePeer".equals(node.getPeer().getClass().getSimpleName()) || Boolean.valueOf(node.getPeer().getAttributes().get("remote.transient")).booleanValue()) { //$NON-NLS-1$ //$NON-NLS-2$
+ doQueryServices(node, new DoneQueryServices() {
+ @Override
+ public void doneQueryServices(Throwable error) {
+ if (error == null) services.set(node.getStringProperty(IPeerModelProperties.PROP_REMOTE_SERVICES));
+ completed.set(true);
+ }
+ });
+ } else {
+ completed.set(true);
+ }
+ }
+ });
+
+ final long startTime = System.currentTimeMillis();
+ final IConditionTester tester = new IConditionTester() {
+ @Override
+ public boolean isConditionFulfilled() {
+ return completed.get();
+ }
+
+ @Override
+ public void cleanup() {}
+ };
+
+ while ((startTime + 1000) < System.currentTimeMillis() && !tester.isConditionFulfilled()) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) { /* ignored on purpose */ }
+ }
+
+ return services.get();
+ }
+
+ /**
+ * Client call back interface for doQueryServices(...).
+ */
+ /* default */ interface DoneQueryServices {
+ /**
+ * Called when the services query completed.
+ *
+ * @param error The error description if operation failed, <code>null</code> if succeeded.
+ */
+ void doneQueryServices(Throwable error);
+ }
+
+ /* default */ final Map<IPeerModel, List<DoneQueryServices>> serviceQueriesInProgress = new HashMap<IPeerModel, List<DoneQueryServices>>();
+
+ /**
+ * Opens a channel to the peer node and query the services from the opened channel.
+ *
+ * @param node The peer node. Must not be <code>null</code>.
+ * @param serviceType The type of the requested services. See {@link IPeerModelProperties#PROP_LOCAL_SERVICES} and {@link IPeerModelProperties#PROP_REMOTE_SERVICES}.
+ * @param done The client callback. Must not be <code>null</code>.
+ */
+ protected void doQueryServices(final IPeerModel node, final DoneQueryServices done) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(node);
+ Assert.isNotNull(done);
+
+ // If a service query for the same peer is already in progress,
+ // attach the new done to the list to call and drop out
+ if (serviceQueriesInProgress.containsKey(node)) {
+ List<DoneQueryServices> dones = serviceQueriesInProgress.get(node);
+ Assert.isNotNull(dones);
+ dones.add(done);
+ return;
+ }
+
+ // Add the done callback to a list of waiting callbacks per peer node
+ List<DoneQueryServices> dones = new ArrayList<DoneQueryServices>();
+ dones.add(done);
+ serviceQueriesInProgress.put(node, dones);
+
+ // Create the inner callback that invokes the queued outer callbacks
+ final DoneQueryServices innerDone = new DoneQueryServices() {
+
+ @Override
+ public void doneQueryServices(Throwable error) {
+ // Get the list of the original done callbacks
+ List<DoneQueryServices> dones = serviceQueriesInProgress.remove(node);
+ for (DoneQueryServices done : dones) {
+ done.doneQueryServices(error);
+ }
+ }
+ };
+
+ // Do not try to open a channel to peers known to be unreachable
+ int state = node.getIntProperty(IPeerModelProperties.PROP_STATE);
+ if (state == IPeerModelProperties.STATE_ERROR || state == IPeerModelProperties.STATE_NOT_REACHABLE || !node.isComplete()) {
+ innerDone.doneQueryServices(null);
+ return;
+ }
+
+ // Opens a channel with the full value-add chain
+ Tcf.getChannelManager().openChannel(node.getPeer(), null, new IChannelManager.DoneOpenChannel() {
+
+ @Override
+ public void doneOpenChannel(Throwable error, IChannel channel) {
+ // If the channel opening failed -> return immediately
+ if (error != null) {
+ innerDone.doneQueryServices(error);
+ } else {
+ // Get the local service
+ List<String> localServices = new ArrayList<String>(channel.getLocalServices());
+ // Get the remote services
+ List<String> remoteServices = new ArrayList<String>(channel.getRemoteServices());
+
+ // Close the channel
+ Tcf.getChannelManager().closeChannel(channel);
+
+ // Sort the service lists
+ Collections.sort(localServices);
+ Collections.sort(remoteServices);
+
+ // Update the services
+ ILocatorModelUpdateService updateService = node.getModel().getService(ILocatorModelUpdateService.class);
+ updateService.updatePeerServices(node, localServices, remoteServices);
+
+ // Invoke the callback
+ innerDone.doneQueryServices(null);
+ }
+ }
+ });
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelRefreshService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelRefreshService.java
index f1bfca9db..16e5b6f4c 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelRefreshService.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelRefreshService.java
@@ -156,8 +156,16 @@ public class LocatorModelRefreshService extends AbstractLocatorModelService impl
else {
oldChildren.remove(peerNode);
}
- // Merge user configured properties between the peers
- model.getService(ILocatorModelUpdateService.class).mergeUserDefinedAttributes(peerNode, peer, false);
+
+ if (peerNode.getPeer() != peer) {
+ if ("RemotePeer".equals(peerNode.getPeer().getClass().getSimpleName())) { //$NON-NLS-1$
+ peerNode.setProperty(IPeerModelProperties.PROP_INSTANCE, peer);
+ } else {
+ // Merge user configured properties between the peers
+ model.getService(ILocatorModelUpdateService.class).mergeUserDefinedAttributes(peerNode, peer, false);
+ }
+ }
+
// Validate the peer node before adding
peerNode = model.validatePeerNodeForAdd(peerNode);
if (peerNode != null) {
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelUpdateService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelUpdateService.java
index 321614c2d..883a30f70 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelUpdateService.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.locator/src/org/eclipse/tcf/te/tcf/locator/services/LocatorModelUpdateService.java
@@ -16,7 +16,6 @@ import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
-import org.eclipse.tcf.core.AbstractPeer;
import org.eclipse.tcf.protocol.IPeer;
import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.te.tcf.core.peers.Peer;
@@ -187,7 +186,7 @@ public class LocatorModelUpdateService extends AbstractLocatorModelService imple
// We can merge the peer attributes only if the destination peer is a AbstractPeer
IPeer dst = node.getPeer();
// If not of correct type, than we cannot update the attributes
- if (!(dst instanceof AbstractPeer) && !(dst instanceof PeerRedirector) && !(dst instanceof Peer)) return;
+ if (!(dst instanceof PeerRedirector) && !(dst instanceof Peer)) return;
// If destination and source peer are the same objects(!) nothing to do here
if (dst == peer) return;
@@ -206,23 +205,38 @@ public class LocatorModelUpdateService extends AbstractLocatorModelService imple
srcAttrs.remove(IPeer.ATTR_NAME);
}
+ // Determine the peer class
+ String peerClassSimpleName = peer.getClass().getSimpleName();
+ if (peer.getAttributes().containsKey("remote.transient")) { //$NON-NLS-1$
+ peerClassSimpleName = "RemotePeer"; //$NON-NLS-1$
+ }
+
// If the source is a RemotePeer and the destination not, attributes from
// the remote peer overwrites local attributes.
- if ("RemotePeer".equals(peer.getClass().getSimpleName()) && !"RemotePeer".equals(dst.getClass().getSimpleName())) { //$NON-NLS-1$ //$NON-NLS-2$
+ if ("RemotePeer".equals(peerClassSimpleName) && !"RemotePeer".equals(dst.getClass().getSimpleName())) { //$NON-NLS-1$ //$NON-NLS-2$
+ // The ID is not merged from remote to local
+ srcAttrs.remove(IPeer.ATTR_ID);
+
// Eliminate all attributes already set in the destination attributes map
+ String merged = dstAttrs.get("remote.merged.transient"); //$NON-NLS-1$
for (String key : dstAttrs.keySet()) {
- srcAttrs.remove(key);
+ if (merged == null || !merged.contains(key)) {
+ srcAttrs.remove(key);
+ }
}
}
// Mark the peer as a remote peer and remember the remote peer id
- if ("RemotePeer".equals(peer.getClass().getSimpleName()) && !"RemotePeer".equals(dst.getClass().getSimpleName())) { //$NON-NLS-1$ //$NON-NLS-2$
+ if ("RemotePeer".equals(peerClassSimpleName) && !"RemotePeer".equals(dst.getClass().getSimpleName())) { //$NON-NLS-1$ //$NON-NLS-2$
srcAttrs.put("remote.transient", Boolean.TRUE.toString()); //$NON-NLS-1$
srcAttrs.put("remote.id.transient", peer.getID()); //$NON-NLS-1$
+ srcAttrs.put("remote.merged.transient", srcAttrs.keySet().toString()); //$NON-NLS-1$
}
// Copy all remaining attributes from source to destination
- if (!srcAttrs.isEmpty()) dstAttrs.putAll(srcAttrs);
+ if (!srcAttrs.isEmpty()) {
+ dstAttrs.putAll(srcAttrs);
+ }
// If the ID's are different between the peers to merge and force is set,
// we have set the ID in dstAttrs to the original one as set in the destination peer.
@@ -231,9 +245,7 @@ public class LocatorModelUpdateService extends AbstractLocatorModelService imple
}
// And update the destination peer attributes
- if (dst instanceof AbstractPeer) {
- ((AbstractPeer)dst).updateAttributes(dstAttrs);
- } else if (dst instanceof PeerRedirector) {
+ if (dst instanceof PeerRedirector) {
((PeerRedirector)dst).updateAttributes(dstAttrs);
} else if (dst instanceof Peer) {
((Peer)dst).updateAttributes(dstAttrs);
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tests/src/org/eclipse/tcf/te/tests/tcf/TcfTestCase.java b/target_explorer/plugins/org.eclipse.tcf.te.tests/src/org/eclipse/tcf/te/tests/tcf/TcfTestCase.java
index f79d47dac..1763f438e 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tests/src/org/eclipse/tcf/te/tests/tcf/TcfTestCase.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tests/src/org/eclipse/tcf/te/tests/tcf/TcfTestCase.java
@@ -1,213 +1,219 @@
-/*******************************************************************************
- * 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.tests.tcf;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.tcf.core.TransientPeer;
-import org.eclipse.tcf.protocol.IPeer;
-import org.eclipse.tcf.protocol.JSON;
-import org.eclipse.tcf.protocol.Protocol;
-import org.eclipse.tcf.te.runtime.model.factory.Factory;
-import org.eclipse.tcf.te.runtime.utils.Host;
-import org.eclipse.tcf.te.runtime.utils.net.IPAddressUtil;
-import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
-import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
-import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService;
-import org.eclipse.tcf.te.tcf.locator.model.Model;
-import org.eclipse.tcf.te.tests.CoreTestCase;
-
-/**
- * TCF test case implementation.
- * <p>
- * Launches a TCF agent at local host and make it available for a test case.
- */
-public class TcfTestCase extends CoreTestCase {
- // The agent launcher instance
- private AgentLauncher launcher;
- // The peer instance
- protected IPeer peer;
- // The peer model instance
- protected IPeerModel peerModel;
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.tests.CoreTestCase#setUp()
- */
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- launchAgent();
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.tests.CoreTestCase#tearDown()
- */
- @Override
- protected void tearDown() throws Exception {
- if (launcher != null) launcher.dispose();
- peer = null;
- peerModel = null;
- super.tearDown();
- }
-
- /**
- * Launches a TCF agent at local host.
- */
- protected void launchAgent() {
- // Get the agent location
- IPath path = getAgentLocation();
- assertNotNull("Cannot determine TCF agent location.", path); //$NON-NLS-1$
- // Add the agent executable name
- path = path.append("agent"); //$NON-NLS-1$
- if (Host.isWindowsHost()) path = path.addFileExtension("exe"); //$NON-NLS-1$
- assertTrue("Invalid agent location: " + path.toString(), path.toFile().isFile()); //$NON-NLS-1$
-
- Throwable error = null;
- String message = null;
-
- // If the agent is not marked executable on Linux, we have to change that
- if (Host.isLinuxHost() && !path.toFile().canExecute()) {
- try {
- Runtime.getRuntime().exec(new String[] { "chmod", "u+x", path.toString() }); //$NON-NLS-1$ //$NON-NLS-2$
- } catch (IOException e) {
- error = e;
- message = e.getLocalizedMessage();
- }
- }
- assertNull("Failed to make the agent executable for the current user.", message); //$NON-NLS-1$
-
- error = null;
- message = null;
-
- assertTrue("Agent should be executable but is not.", path.toFile().canExecute()); //$NON-NLS-1$
-
- // Create the agent launcher
- launcher = new AgentLauncher(path);
- try {
- launcher.launch();
- } catch (Throwable e) {
- error = e;
- message = e.getLocalizedMessage();
- }
- assertNull("Failed to launch agent: " + message, error); //$NON-NLS-1$
-
- error = null;
- message = null;
-
- assertNotNull("Process handle not associated with launcher.", launcher.getProcess()); //$NON-NLS-1$
- assertNotNull("Process output reader not associated with launcher.", launcher.getOutputReader()); //$NON-NLS-1$
-
- Process process = launcher.getProcess();
- int exitCode = -1;
- try {
- exitCode = process.exitValue();
- } catch (IllegalThreadStateException e) {
- error = e;
- message = e.getLocalizedMessage();
- }
- assertNotNull("Agent process died with exit code " + exitCode, error); //$NON-NLS-1$
-
- error = null;
- message = null;
-
- // The agent is started with "-S" to write out the peer attributes in JSON format.
- String output = null;
- int counter = 10;
- while (counter > 0 && output == null) {
- // Try to read in the output
- output = launcher.getOutputReader().getOutput();
- if ("".equals(output)) { //$NON-NLS-1$
- output = null;
- waitAndDispatch(200);
- }
- counter--;
- }
- assertNotNull("Failed to read output from agent.", output); //$NON-NLS-1$
-
- // Strip away "Server-Properties:"
- output = output.replace("Server-Properties:", " "); //$NON-NLS-1$ //$NON-NLS-2$
- output = output.trim();
-
- // Read into an object
+/*******************************************************************************
+ * 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.tests.tcf;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.tcf.core.TransientPeer;
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.protocol.JSON;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.te.runtime.model.factory.Factory;
+import org.eclipse.tcf.te.runtime.utils.Host;
+import org.eclipse.tcf.te.runtime.utils.net.IPAddressUtil;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService;
+import org.eclipse.tcf.te.tcf.locator.model.Model;
+import org.eclipse.tcf.te.tests.CoreTestCase;
+
+/**
+ * TCF test case implementation.
+ * <p>
+ * Launches a TCF agent at local host and make it available for a test case.
+ */
+public class TcfTestCase extends CoreTestCase {
+ // The agent launcher instance
+ private AgentLauncher launcher;
+ // The peer instance
+ protected IPeer peer;
+ // The peer model instance
+ protected IPeerModel peerModel;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tests.CoreTestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ launchAgent();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tests.CoreTestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ if (launcher != null) launcher.dispose();
+ peer = null;
+ peerModel = null;
+ super.tearDown();
+ }
+
+ /**
+ * Launches a TCF agent at local host.
+ */
+ protected void launchAgent() {
+ // Get the agent location
+ IPath path = getAgentLocation();
+ assertNotNull("Cannot determine TCF agent location.", path); //$NON-NLS-1$
+ // Add the agent executable name
+ path = path.append("agent"); //$NON-NLS-1$
+ if (Host.isWindowsHost()) path = path.addFileExtension("exe"); //$NON-NLS-1$
+ assertTrue("Invalid agent location: " + path.toString(), path.toFile().isFile()); //$NON-NLS-1$
+
+ Throwable error = null;
+ String message = null;
+
+ // If the agent is not marked executable on Linux, we have to change that
+ if (Host.isLinuxHost() && !path.toFile().canExecute()) {
+ try {
+ Runtime.getRuntime().exec(new String[] { "chmod", "u+x", path.toString() }); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (IOException e) {
+ error = e;
+ message = e.getLocalizedMessage();
+ }
+ }
+ assertNull("Failed to make the agent executable for the current user.", message); //$NON-NLS-1$
+
+ error = null;
+ message = null;
+
+ assertTrue("Agent should be executable but is not.", path.toFile().canExecute()); //$NON-NLS-1$
+
+ // Create the agent launcher
+ launcher = new AgentLauncher(path);
+ try {
+ launcher.launch();
+ } catch (Throwable e) {
+ error = e;
+ message = e.getLocalizedMessage();
+ }
+ assertNull("Failed to launch agent: " + message, error); //$NON-NLS-1$
+
+ error = null;
+ message = null;
+
+ assertNotNull("Process handle not associated with launcher.", launcher.getProcess()); //$NON-NLS-1$
+ assertNotNull("Process output reader not associated with launcher.", launcher.getOutputReader()); //$NON-NLS-1$
+
+ Process process = launcher.getProcess();
+ int exitCode = -1;
+ try {
+ exitCode = process.exitValue();
+ } catch (IllegalThreadStateException e) {
+ error = e;
+ message = e.getLocalizedMessage();
+ }
+ assertNotNull("Agent process died with exit code " + exitCode, error); //$NON-NLS-1$
+
+ error = null;
+ message = null;
+
+ // The agent is started with "-S" to write out the peer attributes in JSON format.
+ String output = null;
+ int counter = 10;
+ while (counter > 0 && output == null) {
+ // Try to read in the output
+ output = launcher.getOutputReader().getOutput();
+ if ("".equals(output)) { //$NON-NLS-1$
+ output = null;
+ waitAndDispatch(200);
+ }
+ counter--;
+ }
+ assertNotNull("Failed to read output from agent.", output); //$NON-NLS-1$
+
+ // Find the "Server-Properties: ..." string within the output
+ int start = output.indexOf("Server-Properties:"); //$NON-NLS-1$
+ if (start != -1 && start > 0) {
+ output = output.substring(start);
+ }
+
+ // Strip away "Server-Properties:"
+ output = output.replace("Server-Properties:", " "); //$NON-NLS-1$ //$NON-NLS-2$
+ output = output.trim();
+
+ // Read into an object
Object object = parseOne(output);
- @SuppressWarnings("unchecked")
- final Map<String, String> attrs = new HashMap<String, String>((Map<String, String>)object);
-
- // Lookup the corresponding peer object
- final ILocatorModel model = Model.getModel();
- assertNotNull("Failed to access locator model instance.", model); //$NON-NLS-1$
-
- // The expected peer id is "<transport>:<canonical IP>:<port>"
- String transport = attrs.get(IPeer.ATTR_TRANSPORT_NAME);
- assertNotNull("Unexpected return value 'null'.", transport); //$NON-NLS-1$
- String port = attrs.get(IPeer.ATTR_IP_PORT);
- assertNotNull("Unexpected return value 'null'.", port); //$NON-NLS-1$
- String ip = IPAddressUtil.getInstance().getIPv4LoopbackAddress();
- assertNotNull("Unexpected return value 'null'.", ip); //$NON-NLS-1$
-
- final String id = transport + ":" + ip + ":" + port; //$NON-NLS-1$ //$NON-NLS-2$
- final AtomicReference<IPeerModel> node = new AtomicReference<IPeerModel>();
-
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- node.set(model.getService(ILocatorModelLookupService.class).lkupPeerModelById(id));
- // If the peer model is not found by id, try the agent id as fallback.
- if (node.get() == null) {
- String agentID = attrs.get(IPeer.ATTR_AGENT_ID);
- assertNotNull("Unexpected return value 'null'.", agentID); //$NON-NLS-1$
- IPeerModel[] candidates = model.getService(ILocatorModelLookupService.class).lkupPeerModelByAgentId(agentID);
- if (candidates != null && candidates.length > 0) node.set(candidates[0]);
- }
- }
- };
- assertFalse("Test is running in TCF dispatch thread.", Protocol.isDispatchThread()); //$NON-NLS-1$
- Protocol.invokeAndWait(runnable);
-
- // If the peer model is still not found, we create a transient peer
- if (node.get() == null) {
- attrs.put(IPeer.ATTR_ID, id);
- attrs.put(IPeer.ATTR_IP_HOST, ip);
- peer = new TransientPeer(attrs);
- peerModel = Factory.getInstance().newInstance(IPeerModel.class, new Object[] { model, peer });
- } else {
- peerModel = node.get();
- peer = peerModel.getPeer();
- }
- assertNotNull("Failed to determine the peer to use for the tests.", peer); //$NON-NLS-1$
- }
-
- /**
- * Returns the agent location.
- *
- * @return The agent location or <code>null</code> if not found.
- */
- protected IPath getAgentLocation() {
- return getDataLocation("agent", true, true); //$NON-NLS-1$
- }
-
- /**
- * Parses a object from the given encoded string.
- *
- * @param encoded The encoded string. Must not be <code>null</code>.
- * @return The object
+ @SuppressWarnings("unchecked")
+ final Map<String, String> attrs = new HashMap<String, String>((Map<String, String>)object);
+
+ // Lookup the corresponding peer object
+ final ILocatorModel model = Model.getModel();
+ assertNotNull("Failed to access locator model instance.", model); //$NON-NLS-1$
+
+ // The expected peer id is "<transport>:<canonical IP>:<port>"
+ String transport = attrs.get(IPeer.ATTR_TRANSPORT_NAME);
+ assertNotNull("Unexpected return value 'null'.", transport); //$NON-NLS-1$
+ String port = attrs.get(IPeer.ATTR_IP_PORT);
+ assertNotNull("Unexpected return value 'null'.", port); //$NON-NLS-1$
+ String ip = IPAddressUtil.getInstance().getIPv4LoopbackAddress();
+ assertNotNull("Unexpected return value 'null'.", ip); //$NON-NLS-1$
+
+ final String id = transport + ":" + ip + ":" + port; //$NON-NLS-1$ //$NON-NLS-2$
+ final AtomicReference<IPeerModel> node = new AtomicReference<IPeerModel>();
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ node.set(model.getService(ILocatorModelLookupService.class).lkupPeerModelById(id));
+ // If the peer model is not found by id, try the agent id as fallback.
+ if (node.get() == null) {
+ String agentID = attrs.get(IPeer.ATTR_AGENT_ID);
+ assertNotNull("Unexpected return value 'null'.", agentID); //$NON-NLS-1$
+ IPeerModel[] candidates = model.getService(ILocatorModelLookupService.class).lkupPeerModelByAgentId(agentID);
+ if (candidates != null && candidates.length > 0) node.set(candidates[0]);
+ }
+ }
+ };
+ assertFalse("Test is running in TCF dispatch thread.", Protocol.isDispatchThread()); //$NON-NLS-1$
+ Protocol.invokeAndWait(runnable);
+
+ // If the peer model is still not found, we create a transient peer
+ if (node.get() == null) {
+ attrs.put(IPeer.ATTR_ID, id);
+ attrs.put(IPeer.ATTR_IP_HOST, ip);
+ peer = new TransientPeer(attrs);
+ peerModel = Factory.getInstance().newInstance(IPeerModel.class, new Object[] { model, peer });
+ } else {
+ peerModel = node.get();
+ peer = peerModel.getPeer();
+ }
+ assertNotNull("Failed to determine the peer to use for the tests.", peer); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the agent location.
+ *
+ * @return The agent location or <code>null</code> if not found.
+ */
+ protected IPath getAgentLocation() {
+ return getDataLocation("agent", true, true); //$NON-NLS-1$
+ }
+
+ /**
+ * Parses a object from the given encoded string.
+ *
+ * @param encoded The encoded string. Must not be <code>null</code>.
+ * @return The object
*/
- private static Object parseOne(final String encoded) {
- assertNotNull(encoded);
+ private static Object parseOne(final String encoded) {
+ assertNotNull(encoded);
- final AtomicReference<Object> object = new AtomicReference<Object>();
- final AtomicReference<String> message = new AtomicReference<String>();
+ final AtomicReference<Object> object = new AtomicReference<Object>();
+ final AtomicReference<String> message = new AtomicReference<String>();
final AtomicReference<Throwable> error = new AtomicReference<Throwable>();
Runnable runnable = new Runnable() {
@@ -220,13 +226,13 @@ public class TcfTestCase extends CoreTestCase {
message.set(e.getLocalizedMessage());
}
}
- };
- assertFalse("Test is running in TCF dispatch thread.", Protocol.isDispatchThread()); //$NON-NLS-1$
- Protocol.invokeAndWait(runnable);
+ };
+ assertFalse("Test is running in TCF dispatch thread.", Protocol.isDispatchThread()); //$NON-NLS-1$
+ Protocol.invokeAndWait(runnable);
assertNull("Failed to parse server properties: " + message.get(), error.get()); //$NON-NLS-1$
- assertTrue("Server properties object is not of expected type Map.", object.get() instanceof Map); //$NON-NLS-1$
+ assertTrue("Server properties object is not of expected type Map.", object.get() instanceof Map); //$NON-NLS-1$
return object.get();
}
-}
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui.views/src/org/eclipse/tcf/te/ui/views/ViewsUtil.java b/target_explorer/plugins/org.eclipse.tcf.te.ui.views/src/org/eclipse/tcf/te/ui/views/ViewsUtil.java
index ef92b92a1..980c8c485 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.ui.views/src/org/eclipse/tcf/te/ui/views/ViewsUtil.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.ui.views/src/org/eclipse/tcf/te/ui/views/ViewsUtil.java
@@ -14,6 +14,7 @@ import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.tcf.te.ui.views.extensions.CategoriesExtensionPointManager;
import org.eclipse.tcf.te.ui.views.handler.PropertiesCommandHandler;
@@ -113,6 +114,44 @@ public class ViewsUtil {
}
/**
+ * Asynchronously refresh the given element within the view identified
+ * by the given id.
+ *
+ * @param id The view id. Must not be <code>null</code>.
+ * @param element The element to refresh. Must not be <code>null</code>.
+ */
+ public static void refresh(final String id, final Object element) {
+ Assert.isNotNull(id);
+ Assert.isNotNull(element);
+
+ // Create the runnable
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ // Check the active workbench window and active page instances
+ if (PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null && PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() != null) {
+ // Get the view reference
+ IViewReference reference = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findViewReference(id);
+ // Get the view part from the reference, but do not restore it
+ IWorkbenchPart part = reference != null ? reference.getPart(false) : null;
+ // If the part is a common navigator, get the common viewer
+ Viewer viewer = part instanceof CommonNavigator ? ((CommonNavigator)part).getCommonViewer() : null;
+ // If not a common navigator, try to adapt to the viewer
+ if (viewer == null) viewer = part != null ? (Viewer)part.getAdapter(Viewer.class) : null;
+ // Refresh the viewer
+ if (viewer instanceof StructuredViewer) ((StructuredViewer)viewer).refresh(element, true);
+ else viewer.refresh();
+ }
+ }
+ };
+
+ // Execute asynchronously
+ if (PlatformUI.isWorkbenchRunning()) {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(runnable);
+ }
+ }
+
+ /**
* Asynchronously set the given selection to the view identified by the given id.
*
* @param id The view id. Must not be <code>null</code>.

Back to the top