Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Stieber2014-04-23 07:24:04 -0400
committerUwe Stieber2014-04-23 07:26:06 -0400
commit98b0bf8734e100dded514359af808fe2f63395f2 (patch)
tree7272344e9af716a535699927219493187c99d32e
parent244b70627ea39844583a70af64bbffaa77e89b30 (diff)
downloadorg.eclipse.tcf-98b0bf8734e100dded514359af808fe2f63395f2.tar.gz
org.eclipse.tcf-98b0bf8734e100dded514359af808fe2f63395f2.tar.xz
org.eclipse.tcf-98b0bf8734e100dded514359af808fe2f63395f2.zip
Target Explorer: Move stream created event delay and disconnect handling to streams listener proxy implementation
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.core/.options1
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/IChannelManager.java55
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/tracing/ITraceIds.java6
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/internal/ChannelManager.java222
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/launcher/ProcessLauncher.java4
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/launcher/ProcessStreamsListener.java219
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncher.java4
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java224
8 files changed, 417 insertions, 318 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/.options b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/.options
index d8378d5a8..8fb900689 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/.options
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/.options
@@ -1,5 +1,6 @@
org.eclipse.tcf.te.tcf.core/debugmode = 0
org.eclipse.tcf.te.tcf.core/trace/channels = false
org.eclipse.tcf.te.tcf.core/trace/channelManager = false
+org.eclipse.tcf.te.tcf.core/trace/channelManager/streamsListenerProxy = false
org.eclipse.tcf.te.tcf.core/va/logging/enable = false
org.eclipse.tcf.te.tcf.core/va/logging/level = 0x0620
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 9a31534e0..8b3734f68 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2013 Wind River Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2011, 2014 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
@@ -146,6 +146,55 @@ public interface IChannelManager extends IAdaptable {
public void closeAll(boolean wait);
/**
+ * Channel manager specific interface to be implemented by streams listener proxies.
+ */
+ interface IStreamsListenerProxy {
+
+ /**
+ * Trigger the processing of all delayed created events.
+ */
+ void processDelayedCreatedEvents();
+ }
+
+ /**
+ * Channel manager specific extension of the {@link IStreams.StreamsListener} interface
+ * to handle the stream disconnect in a common place.
+ *
+ * @see IStreams.StreamsListener
+ */
+ interface IStreamsListener extends IStreams.StreamsListener {
+
+ /**
+ * Associate the given proxy with the streams listener. The
+ * streams listener can call the proxy methods to tell the
+ * proxy implementation which created stream should be disconnected.
+ *
+ * @param proxy The streams listener proxy or <code>null</code>.
+ */
+ void setProxy(IStreamsListenerProxy proxy);
+
+ /**
+ * Returns if or if not the listener has a context set and can
+ * decide if a created event is consumed or not.
+ *
+ * @return <code>True</code> if the listener has a context, <code>false</code> if not.
+ */
+ boolean hasContext();
+
+ /**
+ * Returns if or if not the given created event is consumed by the streams listener
+ * or not.
+ *
+ * @param stream_type The stream type. Must not be <code>null</code>.
+ * @param stream_id The stream id. Must not be <code>null</code>.
+ * @param context_id The context id or <code>null</code>.
+ *
+ * @return <code>True</code> if the created event is consumed, <code>false</code> otherwise.
+ */
+ boolean isCreatedConsumed(String stream_type, String stream_id, String context_id);
+ }
+
+ /**
* Client call back interface for subscribeStream(...).
*/
interface DoneSubscribeStream {
@@ -165,7 +214,7 @@ public interface IChannelManager extends IAdaptable {
* @param listener The streams listener. Must not be <code>null</code>.
* @param done The client callback. Must not be <code>null</code>.
*/
- public void subscribeStream(IChannel channel, String streamType, IStreams.StreamsListener listener, DoneSubscribeStream done);
+ public void subscribeStream(IChannel channel, String streamType, IStreamsListener listener, DoneSubscribeStream done);
/**
* Client call back interface for unsubscribeStream(...).
@@ -187,5 +236,5 @@ public interface IChannelManager extends IAdaptable {
* @param listener The streams listener. Must not be <code>null</code>.
* @param done The client callback. Must not be <code>null</code>.
*/
- public void unsubscribeStream(IChannel channel, String streamType, IStreams.StreamsListener listener, DoneUnsubscribeStream done);
+ public void unsubscribeStream(IChannel channel, String streamType, IStreamsListener listener, DoneUnsubscribeStream done);
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/tracing/ITraceIds.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/tracing/ITraceIds.java
index 921554482..b997b9448 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/tracing/ITraceIds.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/interfaces/tracing/ITraceIds.java
@@ -23,4 +23,10 @@ public interface ITraceIds {
* If activated, tracing information about the channel manager is printed out.
*/
public static String TRACE_CHANNEL_MANAGER = "trace/channelManager"; //$NON-NLS-1$
+
+ /**
+ * If activated, tracing information about the channel manager streams listener proxies are printed out.
+ */
+ public static final String TRACE_STREAMS_LISTENER_PROXY = "trace/channelManager/streamsListenerProxy"; //$NON-NLS-1$
+
}
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 7540d9448..f8debdb27 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
@@ -11,6 +11,7 @@ package org.eclipse.tcf.te.tcf.core.internal;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
@@ -31,7 +32,6 @@ import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.services.IPathMap;
import org.eclipse.tcf.services.IPathMap.PathMapRule;
import org.eclipse.tcf.services.IStreams;
-import org.eclipse.tcf.services.IStreams.StreamsListener;
import org.eclipse.tcf.te.runtime.callback.Callback;
import org.eclipse.tcf.te.runtime.interfaces.IDisposable;
import org.eclipse.tcf.te.runtime.services.ServiceManager;
@@ -1171,11 +1171,87 @@ public final class ChannelManager extends PlatformObject implements IChannelMana
/**
* Private stream listener proxy implementation.
*/
- private final class StreamListenerProxy implements IStreams.StreamsListener {
+ private final static class StreamListenerProxy implements IStreams.StreamsListener, IChannelManager.IStreamsListenerProxy {
+ // The channel
+ private final IChannel channel;
// The stream type the proxy is registered for
private final String streamType;
// The list of proxied stream listeners
/* default */ ListenerList listeners = new ListenerList();
+ // The list of delayed stream created events
+ private final List<StreamCreatedEvent> delayedCreatedEvents = new ArrayList<StreamCreatedEvent>();
+
+ /**
+ * Immutable stream created event.
+ */
+ private final static class StreamCreatedEvent {
+ /**
+ * The stream type.
+ */
+ public final String streamType;
+ /**
+ * The stream id.
+ */
+ public final String streamId;
+ /**
+ * The context id.
+ */
+ public final String contextId;
+
+ // As the class is immutable, we do not need to build the toString
+ // value again and again. Build it once in the constructor and reuse it later.
+ private final String toString;
+
+ /**
+ * Constructor.
+ *
+ * @param streamType The stream type.
+ * @param streamId The stream id.
+ * @param contextId The context id.
+ */
+ public StreamCreatedEvent(String streamType, String streamId, String contextId) {
+ this.streamType = streamType;
+ this.streamId = streamId;
+ this.contextId = contextId;
+
+ toString = toString();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof StreamCreatedEvent
+ && toString().equals(((StreamCreatedEvent)obj).toString());
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ if (toString != null) return toString;
+
+ StringBuilder builder = new StringBuilder(getClass().getSimpleName());
+ builder.append(": streamType = "); //$NON-NLS-1$
+ builder.append(streamType);
+ builder.append("; streamId = "); //$NON-NLS-1$
+ builder.append(streamId);
+ builder.append("; contextId = "); //$NON-NLS-1$
+ builder.append(contextId);
+
+ return builder.toString();
+ }
+ }
/**
* Constructor
@@ -1186,7 +1262,8 @@ public final class ChannelManager extends PlatformObject implements IChannelMana
Assert.isNotNull(channel);
Assert.isNotNull(streamType);
- channel.addChannelListener(new IChannel.IChannelListener() {
+ this.channel = channel;
+ this.channel.addChannelListener(new IChannel.IChannelListener() {
@Override
public void onChannelOpened() {}
@@ -1227,8 +1304,9 @@ public final class ChannelManager extends PlatformObject implements IChannelMana
*
* @param listener The streams listener. Must not be <code>null</code>.
*/
- public void addListener(IStreams.StreamsListener listener) {
+ public void addListener(IStreamsListener listener) {
Assert.isNotNull(listener);
+ listener.setProxy(this);
listeners.add(listener);
}
@@ -1237,8 +1315,9 @@ public final class ChannelManager extends PlatformObject implements IChannelMana
*
* @param listener The streams listener. Must not be <code>null</code>.
*/
- public void removeListener(IStreams.StreamsListener listener) {
+ public void removeListener(IStreamsListener listener) {
Assert.isNotNull(listener);
+ listener.setProxy(null);
listeners.remove(listener);
}
@@ -1251,13 +1330,112 @@ public final class ChannelManager extends PlatformObject implements IChannelMana
return listeners.isEmpty();
}
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListenerProxy#processDelayedCreatedEvents()
+ */
+ @Override
+ public void processDelayedCreatedEvents() {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY)) {
+ CoreBundleActivator.getTraceHandler().trace("StreamListenerProxy: processDelayedCreatedEvents()", //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY,
+ IStatus.INFO, getClass());
+ }
+
+ synchronized (delayedCreatedEvents) {
+ // Make a snapshot of all delayed created events
+ StreamCreatedEvent[] events = delayedCreatedEvents.toArray(new StreamCreatedEvent[delayedCreatedEvents.size()]);
+ // Clear the events now, it will be refilled by calling the created method
+ delayedCreatedEvents.clear();
+ // Loop the delayed created events and recall the created method to process them
+ for (StreamCreatedEvent event : events) {
+ created(event.streamType, event.streamId, event.contextId);
+ }
+ }
+ }
+
/* (non-Javadoc)
* @see org.eclipse.tcf.services.IStreams.StreamsListener#created(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void created(String stream_type, String stream_id, String context_id) {
+ Assert.isNotNull(stream_type);
+ Assert.isNotNull(stream_id);
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY)) {
+ CoreBundleActivator.getTraceHandler().trace("StreamListenerProxy: created(" + stream_type + ", " + stream_id + ", " + context_id + ")", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY,
+ IStatus.INFO, getClass());
+ }
+
+ // If the context_id is null, disconnect from the stream right away. We do not support
+ // old TCF agents not sending the context id in the created event.
+ if (context_id == null) {
+ IStreams service = channel.getRemoteService(IStreams.class);
+ if (service != null) {
+ service.disconnect(stream_id, new IStreams.DoneDisconnect() {
+ @Override
+ public void doneDisconnect(IToken token, Exception error) {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY)) {
+ CoreBundleActivator.getTraceHandler().trace("StreamListenerProxy: disconnect -> context id must be not null.", //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY, IStatus.INFO, getClass());
+ }
+ }
+ });
+ }
+
+ return;
+ }
+
+ boolean delayed = false;
+ boolean disconnect = true;
+
+ // Loop all listeners
for (Object l : listeners.getListeners()) {
- ((IStreams.StreamsListener)l).created(stream_type, stream_id, context_id);
+ IStreamsListener listener = (IStreamsListener)l;
+
+ // If the listener has no context set yet, the listener cannot decide if
+ // the event is consumed or not. In this case, the event must be delayed.
+ if (!listener.hasContext()) {
+ delayed |= true;
+ continue;
+ }
+
+ // Does the listener consume the event?
+ boolean consume = listener.isCreatedConsumed(stream_type, stream_id, context_id);
+ if (consume) listener.created(stream_type, stream_id, context_id);
+ // If the created event is consumed by one listener, it cannot be disconnected anymore
+ disconnect &= !consume;
+ }
+
+ if (delayed) {
+ // Context not set yet --> add to the delayed list
+ StreamCreatedEvent event = new StreamCreatedEvent(stream_type, stream_id, context_id);
+ synchronized (delayedCreatedEvents) {
+ if (!delayedCreatedEvents.contains(event)) {
+ delayedCreatedEvents.add(event);
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY)) {
+ CoreBundleActivator.getTraceHandler().trace("StreamListenerProxy: delayed -> at least one listener does not have a context set", //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY, IStatus.INFO, getClass());
+ }
+ }
+ }
+ return;
+ }
+
+ if (disconnect) {
+ IStreams service = channel.getRemoteService(IStreams.class);
+ if (service != null) {
+ service.disconnect(stream_id, new IStreams.DoneDisconnect() {
+ @Override
+ public void doneDisconnect(IToken token, Exception error) {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY)) {
+ CoreBundleActivator.getTraceHandler().trace("StreamListenerProxy: disconnect -> not interested in context id", //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY, IStatus.INFO, getClass());
+ }
+ }
+ });
+ }
}
}
@@ -1266,17 +1444,39 @@ public final class ChannelManager extends PlatformObject implements IChannelMana
*/
@Override
public void disposed(String stream_type, String stream_id) {
+ Assert.isNotNull(stream_type);
+ Assert.isNotNull(stream_id);
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY)) {
+ CoreBundleActivator.getTraceHandler().trace("StreamListenerProxy: disposed(" + stream_type + ", " + stream_id + ")", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER_PROXY,
+ IStatus.INFO, getClass());
+ }
+
+ // If the delayed created events list is not empty, we have
+ // to check if one of the delayed create events got disposed
+ synchronized (delayedCreatedEvents) {
+ Iterator<StreamCreatedEvent> iterator = delayedCreatedEvents.iterator();
+ while (iterator.hasNext()) {
+ StreamCreatedEvent event = iterator.next();
+ if (stream_type.equals(event.streamType) && stream_id.equals(event.streamId)) {
+ // Remove the create event from the list
+ iterator.remove();
+ }
+ }
+ }
+
for (Object l : listeners.getListeners()) {
- ((IStreams.StreamsListener)l).disposed(stream_type, stream_id);
+ ((IStreamsListener)l).disposed(stream_type, stream_id);
}
}
}
/* (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager#subscribeStream(org.eclipse.tcf.protocol.IChannel, java.lang.String, org.eclipse.tcf.services.IStreams.StreamsListener, org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.DoneSubscribeStream)
+ * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager#subscribeStream(org.eclipse.tcf.protocol.IChannel, java.lang.String, org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListener, org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.DoneSubscribeStream)
*/
@Override
- public void subscribeStream(final IChannel channel, final String streamType, final StreamsListener listener, final DoneSubscribeStream done) {
+ public void subscribeStream(final IChannel channel, final String streamType, final IStreamsListener listener, final DoneSubscribeStream done) {
Assert.isNotNull(channel);
Assert.isNotNull(streamType);
Assert.isNotNull(listener);
@@ -1344,10 +1544,10 @@ public final class ChannelManager extends PlatformObject implements IChannelMana
}
/* (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager#unsubscribeStream(org.eclipse.tcf.protocol.IChannel, java.lang.String, org.eclipse.tcf.services.IStreams.StreamsListener, org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.DoneUnsubscribeStream)
+ * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager#unsubscribeStream(org.eclipse.tcf.protocol.IChannel, java.lang.String, org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListener, org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.DoneUnsubscribeStream)
*/
@Override
- public void unsubscribeStream(final IChannel channel, final String streamType, final StreamsListener listener, final DoneUnsubscribeStream done) {
+ public void unsubscribeStream(final IChannel channel, final String streamType, final IStreamsListener listener, final DoneUnsubscribeStream done) {
Assert.isNotNull(channel);
Assert.isNotNull(streamType);
Assert.isNotNull(listener);
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/launcher/ProcessLauncher.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/launcher/ProcessLauncher.java
index a5848daa5..8cb876de3 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/launcher/ProcessLauncher.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/launcher/ProcessLauncher.java
@@ -95,7 +95,7 @@ public class ProcessLauncher extends PlatformObject implements IProcessLauncher
private ICallback callback;
// The streams listener instance
- private IStreams.StreamsListener streamsListener = null;
+ private IChannelManager.IStreamsListener streamsListener = null;
// The process listener instance
private IProcesses.ProcessesListener processesListener = null;
// The event listener instance
@@ -1106,7 +1106,7 @@ public class ProcessLauncher extends PlatformObject implements IProcessLauncher
*
* @return The streams listener instance or <code>null</code> if none.
*/
- protected IStreams.StreamsListener createStreamsListener() {
+ protected IChannelManager.IStreamsListener createStreamsListener() {
return new ProcessStreamsListener(this);
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/launcher/ProcessStreamsListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/launcher/ProcessStreamsListener.java
index f5058ce73..ec389c056 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/launcher/ProcessStreamsListener.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/launcher/ProcessStreamsListener.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2013 Wind River Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2011, 2014 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
@@ -34,6 +34,7 @@ import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
import org.eclipse.tcf.te.tcf.core.Tcf;
import org.eclipse.tcf.te.tcf.core.async.CallbackInvocationDelegate;
import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager;
+import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListenerProxy;
import org.eclipse.tcf.te.tcf.core.streams.StreamsDataProvider;
import org.eclipse.tcf.te.tcf.core.streams.StreamsDataReceiver;
import org.eclipse.tcf.te.tcf.core.util.ExceptionUtils;
@@ -46,11 +47,9 @@ import org.eclipse.tcf.util.TCFTask;
/**
* Remote process streams listener implementation.
*/
-public class ProcessStreamsListener implements IStreams.StreamsListener, IProcessContextAwareListener, IDisposable {
+public class ProcessStreamsListener implements IChannelManager.IStreamsListener, IProcessContextAwareListener, IDisposable {
// The channel instance
/* default */ IChannel channel;
- // Flag to signal if the channel is a private or shared channel
- /* default */ boolean sharedChannel;
// The streams service instance
/* default */ IStreams svcStreams;
// The processes service name
@@ -61,82 +60,12 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces
private final List<StreamsDataReceiver> dataReceiver = new ArrayList<StreamsDataReceiver>();
// The stream data provider
private StreamsDataProvider dataProvider;
- // The list of delayed stream created events
- private final List<StreamCreatedEvent> delayedCreatedEvents = new ArrayList<StreamCreatedEvent>();
// The list of created runnable's
private final List<Runnable> runnables = new ArrayList<Runnable>();
-
- /**
- * Immutable stream created event.
- */
- private final static class StreamCreatedEvent {
- /**
- * The stream type.
- */
- public final String streamType;
- /**
- * The stream id.
- */
- public final String streamId;
- /**
- * The context id.
- */
- public final String contextId;
-
- // As the class is immutable, we do not need to build the toString
- // value again and again. Build it once in the constructor and reuse it later.
- private final String toString;
-
- /**
- * Constructor.
- *
- * @param streamType The stream type.
- * @param streamId The stream id.
- * @param contextId The context id.
- */
- public StreamCreatedEvent(String streamType, String streamId, String contextId) {
- this.streamType = streamType;
- this.streamId = streamId;
- this.contextId = contextId;
-
- toString = toString();
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object obj) {
- return obj instanceof StreamCreatedEvent
- && toString().equals(((StreamCreatedEvent)obj).toString());
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return toString().hashCode();
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- if (toString != null) return toString;
-
- StringBuilder builder = new StringBuilder(getClass().getSimpleName());
- builder.append(": streamType = "); //$NON-NLS-1$
- builder.append(streamType);
- builder.append("; streamId = "); //$NON-NLS-1$
- builder.append(streamId);
- builder.append("; contextId = "); //$NON-NLS-1$
- builder.append(contextId);
-
- return builder.toString();
- }
- }
+ // The streams listener proxy instance
+ private IChannelManager.IStreamsListenerProxy proxy = null;
+ // The list of already processed streams created events (simple string in format "<stream type>;<stream id>;<context id>")
+ /* default */ List<String> processedCreatedEvents = new ArrayList<String>();
/**
* Remote process stream reader runnable implementation. The
@@ -654,7 +583,6 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces
public ProcessStreamsListener(ProcessLauncher parent) {
Assert.isNotNull(parent);
this.channel = parent.getChannel();
- this.sharedChannel = parent.isSharedChannel();
this.svcStreams = parent.getSvcStreams();
this.svcProcessesName = parent.getSvcProcesses() instanceof IProcessesV1 ? IProcessesV1.NAME : IProcesses.NAME;
}
@@ -674,7 +602,7 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces
*/
public void dispose(final ICallback callback) {
// Store a final reference to the streams listener instance
- final IStreams.StreamsListener finStreamsListener = this;
+ final IChannelManager.IStreamsListener finStreamsListener = this;
// Store a final reference to the data receivers list
final List<StreamsDataReceiver> finDataReceivers;
@@ -701,6 +629,9 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces
if (callback != null) callback.done(caller, status);
}
});
+
+ // Clean the list of processed created events
+ processedCreatedEvents.clear();
}
}, new CallbackInvocationDelegate());
@@ -721,6 +652,14 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces
collector.initDone();
}
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListener#setProxy(org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListenerProxy)
+ */
+ @Override
+ public void setProxy(IStreamsListenerProxy proxy) {
+ this.proxy = proxy;
+ }
+
/**
* Adds the given receiver to the stream data receiver list.
*
@@ -777,42 +716,48 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces
IStatus.INFO, getClass());
}
- // Loop all delayed create events
- synchronized (delayedCreatedEvents) {
- Iterator<StreamCreatedEvent> iterator = delayedCreatedEvents.iterator();
- while (iterator.hasNext()) {
- final StreamCreatedEvent event = iterator.next();
- // If the created event matches the process context id, re-dispatch the created event
- if (context.getID().equals(event.contextId) || event.contextId == null) {
- created(event.streamType, event.streamId, event.contextId);
- } else if (!sharedChannel) {
- // Disconnect from streams not matching the process context id
- svcStreams.disconnect(event.streamId, new IStreams.DoneDisconnect() {
- @Override
- public void doneDisconnect(IToken token, Exception error) {
- if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
- CoreBundleActivator.getTraceHandler().trace("Remote process stream disconnected (different context): streamId='" + event.streamId + "'", //$NON-NLS-1$ //$NON-NLS-2$
- 0, ITraceIds.TRACE_STREAMS_LISTENER,
- IStatus.INFO, getClass());
- }
- }
- });
- }
- }
- // Clear all events
- delayedCreatedEvents.clear();
- }
+ // Ask the proxy to process all delayed created events
+ if (proxy != null) proxy.processDelayedCreatedEvents();
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.processes.core.interfaces.launcher.IProcessContextAwareListener#getProcessContext()
*/
@Override
- public IProcesses.ProcessContext getProcessContext() {
+ public final IProcesses.ProcessContext getProcessContext() {
return context;
}
/* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListener#hasContext()
+ */
+ @Override
+ public final boolean hasContext() {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("Remote process stream listener: hasContext = " + (context != null), //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER,
+ IStatus.INFO, getClass());
+ }
+ return context != null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListener#isCreatedConsumed(java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Override
+ public final boolean isCreatedConsumed(String stream_type, String stream_id, String context_id) {
+ boolean consumed = context != null && context.getID().equals(context_id);
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("Remote process stream listener: isCreatedConsumed = " + consumed, //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER,
+ IStatus.INFO, getClass());
+ }
+
+ return consumed;
+ }
+
+ /* (non-Javadoc)
* @see org.eclipse.tcf.services.IStreams.StreamsListener#created(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
@@ -826,11 +771,11 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces
IStatus.INFO, getClass());
}
- // If a process context is set, check if the created event is for the
- // monitored process context
- final IProcesses.ProcessContext context = getProcessContext();
- // The contextId is null if used with an older TCF agent not sending the third parameter
- if (context != null && (context.getID().equals(contextId) || contextId == null)) {
+ // Create the internal representation of the created event
+ final String event = streamType + ";" + streamId + ";" + contextId; //$NON-NLS-1$ //$NON-NLS-2$
+
+ // Check if the created event is really consumed by us
+ if (isCreatedConsumed(streamType, streamId, contextId) && !processedCreatedEvents.contains(event)) {
// Create a snapshot of the registered data receivers
StreamsDataReceiver[] receivers;
synchronized (dataReceiver) {
@@ -874,25 +819,10 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces
thread.start();
}
}
- } else if (context != null && !context.getID().equals(contextId) && !sharedChannel) {
- // Streams created event received for a context which is not the
- // one we are interested in. Send a disconnect for those streams.
- svcStreams.disconnect(streamId, new IStreams.DoneDisconnect() {
- @Override
- public void doneDisconnect(IToken token, Exception error) {
- if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
- CoreBundleActivator.getTraceHandler().trace("Remote process stream disconnected (different context): streamId='" + streamId + "'", //$NON-NLS-1$ //$NON-NLS-2$
- 0, ITraceIds.TRACE_STREAMS_LISTENER,
- IStatus.INFO, getClass());
- }
- }
- });
- } else if (context == null) {
- // Context not set yet --> add to the delayed list
- StreamCreatedEvent event = new StreamCreatedEvent(streamType, streamId, contextId);
- synchronized (delayedCreatedEvents) {
- if (!delayedCreatedEvents.contains(event)) delayedCreatedEvents.add(event);
- }
+
+ // Remember that we have seen this event already in order to avoid to process it again
+ // if the streams listener proxy is iterating through delayed events
+ processedCreatedEvents.add(event);
}
}
@@ -904,25 +834,7 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces
// We ignore any other stream type than the associated process service name
if (!svcProcessesName.equals(streamType)) return;
- if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
- CoreBundleActivator.getTraceHandler().trace("Remote process stream disposed: streamId='" + streamId + "'", //$NON-NLS-1$ //$NON-NLS-2$
- 0, ITraceIds.TRACE_STREAMS_LISTENER,
- IStatus.INFO, getClass());
- }
-
- // If the delayed created events list is not empty, we have
- // to check if one of the delayed create events got disposed
- synchronized (delayedCreatedEvents) {
- Iterator<StreamCreatedEvent> iterator = delayedCreatedEvents.iterator();
- while (iterator.hasNext()) {
- StreamCreatedEvent event = iterator.next();
- if (event.streamType != null && event.streamType.equals(streamType)
- && event.streamId != null && event.streamId.equals(streamId)) {
- // Remove the create event from the list
- iterator.remove();
- }
- }
- }
+ boolean consumed = false;
// Stop the thread(s) if the disposed event is for the active
// monitored stream id(s).
@@ -937,9 +849,18 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces
// we cannot wait for a callback here
myRunnable.stop(null);
iterator.remove();
+ consumed |= true;
}
}
}
}
+
+ if (consumed) {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("Remote process stream disposed: streamId='" + streamId + "'", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER,
+ IStatus.INFO, getClass());
+ }
+ }
}
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncher.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncher.java
index 32c24b2a3..22dd3de6e 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncher.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsLauncher.java
@@ -89,7 +89,7 @@ public class TerminalsLauncher extends PlatformObject implements ITerminalsLaunc
private ICallback callback;
// The streams listener instance
- private IStreams.StreamsListener streamsListener = null;
+ private IChannelManager.IStreamsListener streamsListener = null;
// The terminals listener instance
private ITerminals.TerminalsListener terminalsListener = null;
// The event listener instance
@@ -770,7 +770,7 @@ public class TerminalsLauncher extends PlatformObject implements ITerminalsLaunc
*
* @return The streams listener instance or <code>null</code> if none.
*/
- protected IStreams.StreamsListener createStreamsListener() {
+ protected IChannelManager.IStreamsListener createStreamsListener() {
return new TerminalsStreamsListener(this);
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java
index 46b691cb4..0f17b8423 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.terminals.core/src/org/eclipse/tcf/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2013 Wind River Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2011, 2014 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
@@ -32,6 +32,7 @@ import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
import org.eclipse.tcf.te.tcf.core.Tcf;
import org.eclipse.tcf.te.tcf.core.async.CallbackInvocationDelegate;
import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager;
+import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListenerProxy;
import org.eclipse.tcf.te.tcf.core.streams.StreamsDataProvider;
import org.eclipse.tcf.te.tcf.core.streams.StreamsDataReceiver;
import org.eclipse.tcf.te.tcf.core.util.ExceptionUtils;
@@ -44,7 +45,7 @@ import org.eclipse.tcf.util.TCFTask;
/**
* Remote terminal streams listener implementation.
*/
-public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerminalsContextAwareListener {
+public class TerminalsStreamsListener implements IChannelManager.IStreamsListener, ITerminalsContextAwareListener {
// The parent terminals launcher instance
/* default */ final TerminalsLauncher parent;
// The remote terminal context
@@ -53,82 +54,12 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm
private final List<StreamsDataReceiver> dataReceiver = new ArrayList<StreamsDataReceiver>();
// The stream data provider
private StreamsDataProvider dataProvider;
- // The list of delayed stream created events
- private final List<StreamCreatedEvent> delayedCreatedEvents = new ArrayList<StreamCreatedEvent>();
// The list of created runnable's
private final List<Runnable> runnables = new ArrayList<Runnable>();
-
- /**
- * Immutable stream created event.
- */
- private final static class StreamCreatedEvent {
- /**
- * The stream type.
- */
- public final String streamType;
- /**
- * The stream id.
- */
- public final String streamId;
- /**
- * The context id.
- */
- public final String contextId;
-
- // As the class is immutable, we do not need to build the toString
- // value again and again. Build it once in the constructor and reuse it later.
- private final String toString;
-
- /**
- * Constructor.
- *
- * @param streamType The stream type.
- * @param streamId The stream id.
- * @param contextId The context id.
- */
- public StreamCreatedEvent(String streamType, String streamId, String contextId) {
- this.streamType = streamType;
- this.streamId = streamId;
- this.contextId = contextId;
-
- toString = toString();
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object obj) {
- return obj instanceof StreamCreatedEvent
- && toString().equals(((StreamCreatedEvent)obj).toString());
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return toString().hashCode();
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- if (toString != null) return toString;
-
- StringBuilder builder = new StringBuilder(getClass().getSimpleName());
- builder.append(": streamType = "); //$NON-NLS-1$
- builder.append(streamType);
- builder.append("; streamId = "); //$NON-NLS-1$
- builder.append(streamId);
- builder.append("; contextId = "); //$NON-NLS-1$
- builder.append(contextId);
-
- return builder.toString();
- }
- }
+ // The streams listener proxy instance
+ private IChannelManager.IStreamsListenerProxy proxy = null;
+ // The list of already processed streams created events (simple string in format "<stream type>;<stream id>;<context id>")
+ /* default */ List<String> processedCreatedEvents = new ArrayList<String>();
/**
* Remote stream reader runnable implementation.
@@ -694,7 +625,7 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm
*/
public void dispose(final ICallback callback) {
// Store a final reference to the streams listener instance
- final IStreams.StreamsListener finStreamsListener = this;
+ final IChannelManager.IStreamsListener finStreamsListener = this;
// Store a final reference to the data receivers list
final List<StreamsDataReceiver> finDataReceivers;
@@ -721,6 +652,9 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm
if (callback != null) callback.done(caller, status);
}
});
+
+ // Clean the list of processed created events
+ processedCreatedEvents.clear();
}
}, new CallbackInvocationDelegate());
@@ -738,6 +672,14 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm
collector.initDone();
}
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListener#setProxy(org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListenerProxy)
+ */
+ @Override
+ public void setProxy(IStreamsListenerProxy proxy) {
+ this.proxy = proxy;
+ }
+
/**
* Adds the given receiver to the stream data receiver list.
*
@@ -794,42 +736,51 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm
IStatus.INFO, getClass());
}
- // Loop all delayed create events
- synchronized (delayedCreatedEvents) {
- Iterator<StreamCreatedEvent> iterator = delayedCreatedEvents.iterator();
- while (iterator.hasNext()) {
- final StreamCreatedEvent event = iterator.next();
- // If the created event matches the process context id, re-dispatch the created event
- if (context.getID().equals(event.contextId) || context.getProcessID().equals(event.contextId) || event.contextId == null) {
- created(event.streamType, event.streamId, event.contextId);
- } else if (!parent.isSharedChannel()) {
- // Disconnect from streams not matching the process context id
- parent.getSvcStreams().disconnect(event.streamId, new IStreams.DoneDisconnect() {
- @Override
- public void doneDisconnect(IToken token, Exception error) {
- if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
- CoreBundleActivator.getTraceHandler().trace("Remote terminals stream disconnected (different context): streamId='" + event.streamId + "'", //$NON-NLS-1$ //$NON-NLS-2$
- 0, ITraceIds.TRACE_STREAMS_LISTENER,
- IStatus.INFO, getClass());
- }
- }
- });
- }
- }
- // Clear all events
- delayedCreatedEvents.clear();
- }
+ // Ask the proxy to process all delayed created events
+ if (proxy != null) proxy.processDelayedCreatedEvents();
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.terminals.core.interfaces.launcher.ITerminalsContextAwareListener#getTerminalsContext()
*/
@Override
- public TerminalContext getTerminalsContext() {
+ public final TerminalContext getTerminalsContext() {
return context;
}
/* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListener#hasContext()
+ */
+ @Override
+ public final boolean hasContext() {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("Remote terminals stream listener: hasContext = " + (context != null), //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER,
+ IStatus.INFO, getClass());
+ }
+ return context != null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager.IStreamsListener#isCreatedConsumed(java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Override
+ public final boolean isCreatedConsumed(String stream_type, String stream_id, String context_id) {
+ // 2011-10-18: Since the unification of terminals and processes service, the
+ // context id of the streams events is the process context id, not
+ // the terminal context id as before. So check for both here to support
+ // both the older and the newer version of the terminals service.
+ boolean consumed = context != null && (context.getID().equals(context_id) || context.getProcessID().equals(context_id));
+
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("Remote terminals stream listener: isCreatedConsumed = " + consumed, //$NON-NLS-1$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER,
+ IStatus.INFO, getClass());
+ }
+
+ return consumed;
+ }
+ /* (non-Javadoc)
* @see org.eclipse.tcf.services.IStreams.StreamsListener#created(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
@@ -843,16 +794,11 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm
IStatus.INFO, getClass());
}
- // If a terminals context is set, check if the created event is for the
- // monitored terminals context
- final ITerminals.TerminalContext context = getTerminalsContext();
- // The contextId is null if used with an older TCF agent not sending the third parameter
- //
- // 2011-10-18: Since the unification of terminals and processes service, the
- // context id of the streams events is the process context id, not
- // the terminal context id as before. So check for both here to support
- // both the older and the newer version of the terminals service.
- if (context != null && (context.getID().equals(contextId) || context.getProcessID().equals(contextId) || contextId == null)) {
+ // Create the internal representation of the created event
+ final String event = streamType + ";" + streamId + ";" + contextId; //$NON-NLS-1$ //$NON-NLS-2$
+
+ // Check if the created event is really consumed by us
+ if (isCreatedConsumed(streamType, streamId, contextId) && !processedCreatedEvents.contains(event)) {
// Create a snapshot of the registered data receivers
StreamsDataReceiver[] receivers;
synchronized (dataReceiver) {
@@ -896,25 +842,10 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm
thread.start();
}
}
- } else if (context != null && !context.getID().equals(contextId) && !context.getProcessID().equals(contextId) && !parent.isSharedChannel()) {
- // Streams created event received for a context which is not the
- // one we are interested in. Send a disconnect for those streams.
- parent.getSvcStreams().disconnect(streamId, new IStreams.DoneDisconnect() {
- @Override
- public void doneDisconnect(IToken token, Exception error) {
- if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
- CoreBundleActivator.getTraceHandler().trace("Remote terminals stream disconnected (different context): streamId='" + streamId + "'", //$NON-NLS-1$ //$NON-NLS-2$
- 0, ITraceIds.TRACE_STREAMS_LISTENER,
- IStatus.INFO, getClass());
- }
- }
- });
- } else if (context == null) {
- // Context not set yet --> add to the delayed list
- StreamCreatedEvent event = new StreamCreatedEvent(streamType, streamId, contextId);
- synchronized (delayedCreatedEvents) {
- if (!delayedCreatedEvents.contains(event)) delayedCreatedEvents.add(event);
- }
+
+ // Remember that we have seen this event already in order to avoid to process it again
+ // if the streams listener proxy is iterating through delayed events
+ processedCreatedEvents.add(event);
}
}
@@ -926,25 +857,7 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm
// We ignore any other stream type than ITerminals.NAME
if (!ITerminals.NAME.equals(streamType)) return;
- if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
- CoreBundleActivator.getTraceHandler().trace("Remote terminals stream disposed: streamId='" + streamId + "'", //$NON-NLS-1$ //$NON-NLS-2$
- 0, ITraceIds.TRACE_STREAMS_LISTENER,
- IStatus.INFO, getClass());
- }
-
- // If the delayed created events list is not empty, we have
- // to check if one of the delayed create events got disposed
- synchronized (delayedCreatedEvents) {
- Iterator<StreamCreatedEvent> iterator = delayedCreatedEvents.iterator();
- while (iterator.hasNext()) {
- StreamCreatedEvent event = iterator.next();
- if (event.streamType != null && event.streamType.equals(streamType)
- && event.streamId != null && event.streamId.equals(streamId)) {
- // Remove the create event from the list
- iterator.remove();
- }
- }
- }
+ boolean consumed = false;
// Stop the thread(s) if the disposed event is for the active
// monitored stream id(s).
@@ -959,9 +872,18 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm
// we cannot wait for a callback here
myRunnable.stop(null);
iterator.remove();
+ consumed |= true;
}
}
}
}
+
+ if (consumed) {
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_STREAMS_LISTENER)) {
+ CoreBundleActivator.getTraceHandler().trace("Remote terminals stream disposed: streamId='" + streamId + "'", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STREAMS_LISTENER,
+ IStatus.INFO, getClass());
+ }
+ }
}
}

Back to the top