/*******************************************************************************
* Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved.
* This program and the accompanying materials are made available under the terms
* of the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tm.te.tcf.core.internal;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.tm.tcf.core.AbstractPeer;
import org.eclipse.tm.tcf.core.TransientPeer;
import org.eclipse.tm.tcf.protocol.IChannel;
import org.eclipse.tm.tcf.protocol.IPeer;
import org.eclipse.tm.tcf.protocol.Protocol;
import org.eclipse.tm.te.tcf.core.interfaces.IChannelManager;
/**
* TCF channel manager implementation.
*/
public final class ChannelManager extends PlatformObject implements IChannelManager {
/**
* Constructor.
*/
public ChannelManager() {
super();
}
/* (non-Javadoc)
* @see org.eclipse.tm.te.tcf.core.interfaces.IChannelManager#openChannel(org.eclipse.tm.tcf.protocol.IPeer, org.eclipse.tm.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel)
*/
@Override
public void openChannel(final IPeer peer, final DoneOpenChannel done) {
if (Protocol.isDispatchThread()) {
internalOpenChannel(peer, done);
} else {
Protocol.invokeLater(new Runnable() {
@Override
public void run() {
internalOpenChannel(peer, done);
}
});
}
}
/**
* Internal implementation of {@link #openChannel(IPeer, org.eclipse.tm.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel)}.
* <p>
* Method must be called within the TCF dispatch thread.
*
* @param peer The peer. Must not be <code>null</code>.
* @param done The client callback. Must not be <code>null</code>.
*/
/* default */ void internalOpenChannel(final IPeer peer, final DoneOpenChannel done) {
Assert.isNotNull(peer);
Assert.isNotNull(done);
Assert.isTrue(Protocol.isDispatchThread());
// Open the channel
final IChannel channel = peer.openChannel();
// Register the channel listener
if (channel != null) {
channel.addChannelListener(new IChannel.IChannelListener() {
@Override
public void onChannelOpened() {
// Remove ourself as listener from the channel
channel.removeChannelListener(this);
// Channel opening succeeded
done.doneOpenChannel(null, channel);
}
@Override
public void onChannelClosed(Throwable error) {
// Remove ourself as listener from the channel
channel.removeChannelListener(this);
// Channel opening failed
done.doneOpenChannel(error, channel);
}
@Override
public void congestionLevel(int level) {
// ignored
}
});
} else {
// Channel is null? Something went terrible wrong.
done.doneOpenChannel(new Exception("Unexpected null return value from IPeer#openChannel()!"), null); //$NON-NLS-1$
}
}
/* (non-Javadoc)
* @see org.eclipse.tm.te.tcf.core.interfaces.IChannelManager#openChannel(java.util.Map, org.eclipse.tm.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel)
*/
@Override
public void openChannel(final Map<String, String> peerAttributes, final DoneOpenChannel done) {
if (Protocol.isDispatchThread()) {
internalOpenChannel(peerAttributes, done);
} else {
Protocol.invokeLater(new Runnable() {
@Override
public void run() {
internalOpenChannel(peerAttributes, done);
}
});
}
}
/**
* Internal implementation of {@link #openChannel(Map, org.eclipse.tm.te.tcf.core.interfaces.IChannelManager.DoneOpenChannel)}.
* <p>
* Method must be called within the TCF dispatch thread.
*
* @param peerAttributes The peer attributes. Must not be <code>null</code>.
* @param done The client callback. Must not be <code>null</code>.
*/
/* default */ void internalOpenChannel(final Map<String, String> peerAttributes, final DoneOpenChannel done) {
Assert.isNotNull(peerAttributes);
Assert.isNotNull(done);
Assert.isTrue(Protocol.isDispatchThread());
internalOpenChannel(getOrCreatePeerInstance(peerAttributes), done);
}
/**
* Tries to find an existing peer instance or create an new {@link IPeer}
* instance if not found.
* <p>
* <b>Note:</b> This method must be invoked at the TCF dispatch thread.
*
* @param peerAttributes The peer attributes. Must not be <code>null</code>.
* @return The peer instance.
*/
private IPeer getOrCreatePeerInstance(final Map<String, String> peerAttributes) {
Assert.isNotNull(peerAttributes);
Assert.isTrue(Protocol.isDispatchThread());
// Get the peer id from the properties
String peerId = peerAttributes.get(IPeer.ATTR_ID);
Assert.isNotNull(peerId);
// Check if we shall open the peer transient
boolean isTransient = peerAttributes.containsKey("transient") ? Boolean.parseBoolean(peerAttributes.remove("transient")) : false; //$NON-NLS-1$ //$NON-NLS-2$
// Look the peer via the Locator Service.
IPeer peer = Protocol.getLocator().getPeers().get(peerId);
// If not peer could be found, create a new one
if (peer == null) {
peer = isTransient ? new TransientPeer(peerAttributes) : new AbstractPeer(peerAttributes);
}
// Return the peer instance
return peer;
}
}