diff options
Diffstat (limited to 'plugins')
5 files changed, 238 insertions, 48 deletions
diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java index 6056358e7..d3942284b 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; @@ -951,6 +952,46 @@ class TCFSelfTest { } })); } + if (!reg_map.isEmpty()) { + Random rnd = new Random(); + List<IRegisters.Location> locs = new ArrayList<IRegisters.Location>(); + String[] ids = reg_map.keySet().toArray(new String[reg_map.size()]); + for (int i = 0; i < rnd.nextInt(32); i++) { + String id = ids[rnd.nextInt(ids.length)]; + IRegisters.RegistersContext ctx = reg_map.get(id); + if (!ctx.isReadable()) continue; + if (ctx.isReadOnce()) continue; + int offs = rnd.nextInt(ctx.getSize()); + int size = rnd.nextInt(ctx.getSize() - offs) + 1; + locs.add(new IRegisters.Location(id, offs, size)); + } + final IRegisters.Location[] loc_arr = locs.toArray(new IRegisters.Location[locs.size()]); + cmds.add(rg.getm(loc_arr, new IRegisters.DoneGet() { + public void doneGet(IToken token, Exception error, byte[] value) { + cmds.remove(token); + if (suspended.get(sc.id) != sc) return; + if (error != null) { + for (IToken t : cmds) t.cancel(); + exit(error); + return; + } + cmds.add(rg.setm(loc_arr, value, new IRegisters.DoneSet() { + public void doneSet(IToken token, Exception error) { + cmds.remove(token); + if (suspended.get(sc.id) != sc) return; + if (error != null) { + for (IToken t : cmds) t.cancel(); + exit(error); + return; + } + if (cmds.isEmpty()) { + resume(sc); + } + } + })); + } + })); + } if (cmds.isEmpty()) { resume(sc); } diff --git a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java index ace101013..dda4db59e 100644 --- a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java +++ b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.tm.internal.tcf.services.local; +import java.lang.reflect.Method; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; @@ -18,6 +19,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.eclipse.tm.internal.tcf.core.LocalPeer; @@ -174,52 +176,61 @@ public class LocatorService implements ILocator { * socket.send(new DatagramPacket(buf, buf.length, ia.getBroadcast(), 1534)); * } */ - Enumeration<InetAddress> n = f.getInetAddresses(); - while (n.hasMoreElements()) { - InetAddress ina = n.nextElement(); - byte[] adr = ina.getAddress(); - if (adr.length != 4) { - // TODO: Support IPv6 - // System.out.println("Dont support IPv6: " + ina); - continue; - } - /* Since we don't know actual broadcast address, - * lets try different combinations. - * Hopefully one of them will work. - */ - int h = adr[0] & 0xff; - if (h >= 1 && h <= 127 && h != 38) { - adr[3] = (byte)255; - socket.send(new DatagramPacket(buf, buf.length, - InetAddress.getByAddress(null, adr), 1534)); - adr[2] = (byte)255; - socket.send(new DatagramPacket(buf, buf.length, - InetAddress.getByAddress(null, adr), 1534)); - adr[1] = (byte)255; - } - else if (h >= 128 && h <= 191) { - adr[3] = (byte)255; - socket.send(new DatagramPacket(buf, buf.length, - InetAddress.getByAddress(null, adr), 1534)); - adr[2] = (byte)255; + try { + Method m0 = f.getClass().getMethod("getInterfaceAddresses"); + for (Object ia : (List<?>)m0.invoke(f)) { + Method m1 = ia.getClass().getMethod("getBroadcast"); + socket.send(new DatagramPacket(buf, buf.length, (InetAddress)m1.invoke(ia), 1534)); } - else { - adr[3] = (byte)(adr[3] | 0x0f); - socket.send(new DatagramPacket(buf, buf.length, - InetAddress.getByAddress(null, adr), 1534)); - adr[3] = (byte)(adr[3] | 0x01f); - socket.send(new DatagramPacket(buf, buf.length, - InetAddress.getByAddress(null, adr), 1534)); - adr[3] = (byte)(adr[3] | 0x03f); - socket.send(new DatagramPacket(buf, buf.length, - InetAddress.getByAddress(null, adr), 1534)); - adr[3] = (byte)(adr[3] | 0x07f); + } + catch (Exception x) { + Enumeration<InetAddress> n = f.getInetAddresses(); + while (n.hasMoreElements()) { + InetAddress ina = n.nextElement(); + byte[] adr = ina.getAddress(); + if (adr.length != 4) { + // TODO: Support IPv6 + // System.out.println("Don't support IPv6: " + ina); + continue; + } + /* Since we don't know actual broadcast address, + * lets try different combinations. + * Hopefully one of them will work. + */ + int h = adr[0] & 0xff; + if (h >= 1 && h <= 127 && h != 38) { + adr[3] = (byte)255; + socket.send(new DatagramPacket(buf, buf.length, + InetAddress.getByAddress(null, adr), 1534)); + adr[2] = (byte)255; + socket.send(new DatagramPacket(buf, buf.length, + InetAddress.getByAddress(null, adr), 1534)); + adr[1] = (byte)255; + } + else if (h >= 128 && h <= 191) { + adr[3] = (byte)255; + socket.send(new DatagramPacket(buf, buf.length, + InetAddress.getByAddress(null, adr), 1534)); + adr[2] = (byte)255; + } + else { + adr[3] = (byte)(adr[3] | 0x0f); + socket.send(new DatagramPacket(buf, buf.length, + InetAddress.getByAddress(null, adr), 1534)); + adr[3] = (byte)(adr[3] | 0x01f); + socket.send(new DatagramPacket(buf, buf.length, + InetAddress.getByAddress(null, adr), 1534)); + adr[3] = (byte)(adr[3] | 0x03f); + socket.send(new DatagramPacket(buf, buf.length, + InetAddress.getByAddress(null, adr), 1534)); + adr[3] = (byte)(adr[3] | 0x07f); + socket.send(new DatagramPacket(buf, buf.length, + InetAddress.getByAddress(null, adr), 1534)); + adr[3] = (byte)255; + } socket.send(new DatagramPacket(buf, buf.length, InetAddress.getByAddress(null, adr), 1534)); - adr[3] = (byte)255; } - socket.send(new DatagramPacket(buf, buf.length, - InetAddress.getByAddress(null, adr), 1534)); } } } diff --git a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/RegistersProxy.java b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/RegistersProxy.java index 42424c063..5c64aae33 100644 --- a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/RegistersProxy.java +++ b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/RegistersProxy.java @@ -208,6 +208,37 @@ public class RegistersProxy implements IRegisters { }.token; } + public IToken getm(Location[] locs, final DoneGet done) { + return new Command(channel, this, "getm", new Object[]{ locs }) { + @SuppressWarnings("unchecked") + @Override + public void done(Exception error, Object[] args) { + byte[] val = null; + if (error == null) { + assert args.length == 3; + error = toError(args[0], args[1]); + String str = (String)args[2]; + if (str != null) val = Base64.toByteArray(str.toCharArray()); + } + done.doneGet(token, error, val); + } + }.token; + } + + public IToken setm(Location[] locs, byte[] value, final DoneSet done) { + return new Command(channel, this, "setm", + new Object[]{ locs, Base64.toBase64(value, 0, value.length) }) { + @Override + public void done(Exception error, Object[] args) { + if (error == null) { + assert args.length == 2; + error = toError(args[0], args[1]); + } + done.doneSet(token, error); + } + }.token; + } + public void addListener(final RegistersListener listener) { IChannel.IEventListener l = new IChannel.IEventListener() { @@ -294,4 +325,19 @@ public class RegistersProxy implements IRegisters { } return arr; } + + static { + JSON.addObjectWriter(Location.class, new JSON.ObjectWriter() { + public void write(Object o) throws IOException { + Location l = (Location)o; + JSON.write('['); + JSON.writeObject(l.id); + JSON.write(','); + JSON.writeUInt(l.offs); + JSON.write(','); + JSON.writeUInt(l.size); + JSON.write(']'); + } + }); + } } diff --git a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/protocol/JSON.java b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/protocol/JSON.java index e5dd10c61..f5000fed5 100644 --- a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/protocol/JSON.java +++ b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/protocol/JSON.java @@ -30,10 +30,29 @@ import org.eclipse.tm.internal.tcf.core.ReadOnlyMap; /** * JSON is TCF preferred marshaling. This class implements generation and parsing of JSON strings. - * The code is optimized for speed since it is a time-critical part of the framework. + * The code is optimized for speed since it is a time-critical part of the framework. + * + * Reading of JSON produces data structure that consists of objects of these classes: + * Boolean, Number, String, Collection, Map. + * + * Writing of JSON is supported for: + * Boolean, Number, String, char[], byte[], Object[], Collection, Map + * + * Clients can enable writing support for objects of a other classes by + * registering ObjectWriter interface implementation. */ public class JSON { + /** + * Clients implement ObjectWriter interface when they want to enable marshaling of + * object classes that are not directly supported by JSON library. + */ + public interface ObjectWriter { + void write(Object o) throws IOException; + } + + private static final Map<Class<?>,ObjectWriter> object_writers = new HashMap<Class<?>,ObjectWriter>(); + private static char[] tmp_buf = new char[0x1000]; private static byte[] tmp_bbf = new byte[0x1000]; private static int tmp_buf_pos; @@ -48,8 +67,22 @@ public class JSON { private static final char[] err_buf = new char[100]; private static int err_buf_pos; private static int err_buf_cnt; + + /** + * Add a handler for converting objects of a particular class into JSON. + * @param cls - a class + * @param writer - ObjectWriter implementation that provides generation of JSON for a given class. + */ + public static void addObjectWriter(Class<?> cls, ObjectWriter writer) { + object_writers.put(cls, writer); + } - private static void write(char ch) { + /** + * Write a character into JSON output buffer. + * Clients should not call this method directly, except from ObjectWriter implementation. + * @param ch + */ + public static void write(char ch) { if (tmp_buf_pos >= tmp_buf.length) { char[] tmp = new char[tmp_buf.length * 2]; System.arraycopy(tmp_buf, 0, tmp, 0, tmp_buf_pos); @@ -58,7 +91,13 @@ public class JSON { tmp_buf[tmp_buf_pos++] = ch; } - private static void write(String s) { + /** + * Write a string into JSON output buffer. + * The string is written "as-is". Call writeObject() to convert a String into JSON string. + * Clients should not call this method directly, except from ObjectWriter implementation. + * @param s - a string + */ + public static void write(String s) { int l = s.length(); for (int i = 0; i < l; i++) { char ch = s.charAt(i); @@ -67,7 +106,12 @@ public class JSON { } } - private static void writeUInt(int n) { + /** + * Write a non-negative integer number into JSON output buffer. + * Clients should not call this method directly, except from ObjectWriter implementation. + * @param n - a number + */ + public static void writeUInt(int n) { assert n >= 0; if (n >= 10) writeUInt(n / 10); write((char)('0' + n % 10)); @@ -320,8 +364,13 @@ public class JSON { return l.toArray(); } + /** + * Write an object into JSON output buffer. + * Clients should not call this method directly, except from ObjectWriter implementation. + * @param o - an object to write + */ @SuppressWarnings("unchecked") - private static void writeObject(Object o) throws IOException { + public static void writeObject(Object o) throws IOException { if (o == null) { write("null"); } @@ -419,7 +468,13 @@ public class JSON { write('}'); } else { - throw new IOException("JSON: unsupported object type"); + ObjectWriter writer = object_writers.get(o.getClass()); + if (writer != null) { + writer.write(o); + } + else { + throw new IOException("JSON: unsupported object type"); + } } } diff --git a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IRegisters.java b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IRegisters.java index 9fb1de145..73625f295 100644 --- a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IRegisters.java +++ b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IRegisters.java @@ -258,6 +258,43 @@ public interface IRegisters extends IService { } /** + * Read values of multiple locations in registers. + * @param locs - array of data locations. + * @param done - call back object. + * @return - pending command handle. + */ + IToken getm(Location[] locs, DoneGet done); + + /** + * Set values of multiple locations in registers. + * @param locs - array of data locations. + * @param value - value to write into the context. + * @param done - call back object. + * @return - pending command handle. + */ + IToken setm(Location[] locs, byte[] value, DoneSet done); + + /** + * Class Location represents value location in register context + */ + final class Location { + /** Register context ID */ + public final String id; + + /** offset in the context, in bytes */ + public final int offs; + + /** value size in byte */ + public final int size; + + public Location(String id, int offs, int size) { + this.id = id; + this.offs = offs; + this.size = size; + } + } + + /** * 'get' command call back interface. */ interface DoneGet { |