diff options
Diffstat (limited to 'target_explorer/plugins')
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>. |