diff options
Diffstat (limited to 'plugins/org.eclipse.tcf.core/src/org/eclipse/tcf/internal/services/remote/LocatorProxy.java')
-rw-r--r-- | plugins/org.eclipse.tcf.core/src/org/eclipse/tcf/internal/services/remote/LocatorProxy.java | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/plugins/org.eclipse.tcf.core/src/org/eclipse/tcf/internal/services/remote/LocatorProxy.java b/plugins/org.eclipse.tcf.core/src/org/eclipse/tcf/internal/services/remote/LocatorProxy.java new file mode 100644 index 000000000..d5be57e2c --- /dev/null +++ b/plugins/org.eclipse.tcf.core/src/org/eclipse/tcf/internal/services/remote/LocatorProxy.java @@ -0,0 +1,222 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 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.internal.tcf.services.remote; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.tm.tcf.core.Command; +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.IToken; +import org.eclipse.tm.tcf.protocol.JSON; +import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.tcf.services.ILocator; + + +public class LocatorProxy implements ILocator { + + private final IChannel channel; + private final Map<String,IPeer> peers = new HashMap<String,IPeer>(); + private final Collection<LocatorListener> listeners = new ArrayList<LocatorListener>(); + + private boolean get_peers_done = false; + + private class Peer extends TransientPeer { + + private final IPeer parent; + + Peer(IPeer parent, Map<String,String> attrs) { + super(attrs); + this.parent = parent; + } + + public IChannel openChannel() { + assert Protocol.isDispatchThread(); + IChannel c = parent.openChannel(); + c.redirect(getID()); + return c; + } + }; + + private final IChannel.IEventListener event_listener = new IChannel.IEventListener() { + + @SuppressWarnings("unchecked") + public void event(String name, byte[] data) { + try { + Object[] args = JSON.parseSequence(data); + if (name.equals("peerAdded")) { + assert args.length == 1; + IPeer peer = new Peer(channel.getRemotePeer(), (Map<String,String>)args[0]); + if (peers.get(peer.getID()) != null) { + Protocol.log("Invalid peerAdded event", new Error()); + return; + } + peers.put(peer.getID(), peer); + for (LocatorListener l : listeners.toArray(new LocatorListener[listeners.size()])) { + try { + l.peerAdded(peer); + } + catch (Throwable x) { + Protocol.log("Unhandled exception in Locator listener", x); + } + } + } + else if (name.equals("peerChanged")) { + assert args.length == 1; + Map<String,String> m = (Map<String,String>)args[0]; + if (m == null) throw new Error("Locator service: invalid peerChanged event - no peer ID"); + IPeer peer = peers.get(m.get(IPeer.ATTR_ID)); + if (peer == null) return; + peers.put(peer.getID(), peer); + for (LocatorListener l : listeners.toArray(new LocatorListener[listeners.size()])) { + try { + l.peerChanged(peer); + } + catch (Throwable x) { + Protocol.log("Unhandled exception in Locator listener", x); + } + } + } + else if (name.equals("peerRemoved")) { + assert args.length == 1; + String id = (String)args[0]; + IPeer peer = peers.remove(id); + if (peer == null) return; + for (LocatorListener l : listeners.toArray(new LocatorListener[listeners.size()])) { + try { + l.peerRemoved(id); + } + catch (Throwable x) { + Protocol.log("Unhandled exception in Locator listener", x); + } + } + } + else if (name.equals("peerHeartBeat")) { + assert args.length == 1; + String id = (String)args[0]; + IPeer peer = peers.get(id); + if (peer == null) return; + for (LocatorListener l : listeners.toArray(new LocatorListener[listeners.size()])) { + try { + l.peerHeartBeat(id); + } + catch (Throwable x) { + Protocol.log("Unhandled exception in Locator listener", x); + } + } + } + else { + throw new IOException("Locator service: unknown event: " + name); + } + } + catch (Throwable x) { + channel.terminate(x); + } + } + }; + + public LocatorProxy(IChannel channel) { + this.channel = channel; + channel.addEventListener(this, event_listener); + } + + public String getName() { + return NAME; + } + + public Map<String,IPeer> getPeers() { + return peers; + } + + public IToken redirect(String peer_id, final DoneRedirect done) { + return new Command(channel, this, "redirect", new Object[]{ peer_id }) { + @Override + public void done(Exception error, Object[] args) { + if (error == null) { + assert args.length == 1; + error = toError(args[0]); + } + done.doneRedirect(token, error); + } + }.token; + } + + public IToken redirect(Map<String,String> peer, final DoneRedirect done) { + return new Command(channel, this, "redirect", new Object[]{ peer }) { + @Override + public void done(Exception error, Object[] args) { + if (error == null) { + assert args.length == 1; + error = toError(args[0]); + } + done.doneRedirect(token, error); + } + }.token; + } + + public IToken sync(final DoneSync done) { + return new Command(channel, this, "sync", null) { + @Override + public void done(Exception error, Object[] args) { + if (error != null) channel.terminate(error); + done.doneSync(token); + } + }.token; + } + + public void addListener(LocatorListener listener) { + listeners.add(listener); + if (!get_peers_done) { + new Command(channel, this, "getPeers", null) { + @SuppressWarnings("unchecked") + @Override + public void done(Exception error, Object[] args) { + if (error == null) { + assert args.length == 2; + error = toError(args[0]); + } + if (error != null) { + Protocol.log("Locator error", error); + return; + } + Collection<?> c = (Collection<?>)args[1]; + if (c != null) { + for (Object o : c) { + Map<String,String> m = (Map<String,String>)o; + String id = m.get(IPeer.ATTR_ID); + if (peers.get(id) != null) continue; + IPeer peer = new Peer(channel.getRemotePeer(), m); + peers.put(id, peer); + for (LocatorListener l : listeners.toArray(new LocatorListener[listeners.size()])) { + try { + l.peerAdded(peer); + } + catch (Throwable x) { + Protocol.log("Unhandled exception in Locator listener", x); + } + } + } + } + } + }; + get_peers_done = true; + } + } + + public void removeListener(LocatorListener listener) { + listeners.remove(listener); + } +} |