From 6f338b55f673f4bc30dcb665576e11185ab23932 Mon Sep 17 00:00:00 2001 From: Matthew Johnson Date: Sun, 2 Dec 2007 20:12:45 +0000 Subject: add fallback objects --- changelog | 2 + debug.conf | 1 + org/freedesktop/dbus/AbstractConnection.java | 65 +++++++++++++++++++++++++++- org/freedesktop/dbus/test/test.java | 7 ++- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/changelog b/changelog index 4e68933..6a9c161 100644 --- a/changelog +++ b/changelog @@ -7,6 +7,8 @@ Version 2.4: (pointed out by Serkan Kaba ) * Automatically unexport objects which go out of scope in the parent program (don't hold a strong reference). + * Add fallback objects---a single object can be called for any + object under a given path prefix. Version 2.3.2: diff --git a/debug.conf b/debug.conf index 272642a..6843191 100644 --- a/debug.conf +++ b/debug.conf @@ -4,6 +4,7 @@ org.freedesktop.dbus.Message = ERR org.freedesktop.dbus.MethodCall = ERR org.freedesktop.dbus.MethodTuple = ERR org.freedesktop.dbus.AbstractConnection = VERBOSE +org.freedesktop.dbus.AbstractConnection$FallbackContainer = VERBOSE org.freedesktop.dbus.AbstractConnection$_thread = ERR org.freedesktop.dbus.AbstractConnection$_sender = ERR org.freedesktop.dbus.DirectConnection = ERR diff --git a/org/freedesktop/dbus/AbstractConnection.java b/org/freedesktop/dbus/AbstractConnection.java index 6d45c69..2a9b74c 100644 --- a/org/freedesktop/dbus/AbstractConnection.java +++ b/org/freedesktop/dbus/AbstractConnection.java @@ -41,6 +41,37 @@ import cx.ath.matthew.debug.Debug; */ public abstract class AbstractConnection { + protected class FallbackContainer + { + private Map fallbacks = new HashMap(); + public synchronized void add(String path, ExportedObject eo) + { + if (Debug.debug) Debug.print(Debug.DEBUG, "Adding fallback on "+path+" of "+eo); + fallbacks.put(path.split("/"), eo); + } + public synchronized void remove(String path) + { + if (Debug.debug) Debug.print(Debug.DEBUG, "Removing fallback on "+path); + fallbacks.remove(path.split("/")); + } + public synchronized ExportedObject get(String path) + { + int best = 0; + int i = 0; + ExportedObject bestobject = null; + String[] pathel = path.split("/"); + for (String[] fbpath: fallbacks.keySet()) { + if (Debug.debug) Debug.print(Debug.VERBOSE, "Trying fallback path "+Arrays.deepToString(fbpath)+" to match "+Arrays.deepToString(pathel)); + for (i = 0; i < pathel.length && i < fbpath.length; i++) + if (!pathel[i].equals(fbpath[i])) break; + if (i > 0 && i == fbpath.length && i > best) + bestobject = fallbacks.get(fbpath); + if (Debug.debug) Debug.print(Debug.VERBOSE, "Matches "+i+" bestobject now "+bestobject); + } + if (Debug.debug) Debug.print(Debug.DEBUG, "Found fallback for "+path+" of "+bestobject); + return bestobject; + } + } protected class _thread extends Thread { public _thread() @@ -199,6 +230,7 @@ public abstract class AbstractConnection protected Map pendingCallbackReplys; protected LinkedList runnables; protected LinkedList<_workerthread> workers; + protected FallbackContainer fallbackcontainer; protected boolean _run; EfficientQueue outgoing; LinkedList pendingErrors; @@ -250,6 +282,7 @@ public abstract class AbstractConnection runnables = new LinkedList(); workers = new LinkedList<_workerthread>(); objectTree = new ObjectTree(); + fallbackcontainer = new FallbackContainer(); synchronized (workers) { for (int i = 0; i < THREADCOUNT; i++) { _workerthread t = new _workerthread(); @@ -333,7 +366,7 @@ public abstract class AbstractConnection /** * Export an object so that its methods can be called on DBus. - * @param objectpath The path to the object we are exposing. MUST be in slash-notation, like "org/freedesktop/Local", + * @param objectpath The path to the object we are exposing. MUST be in slash-notation, like "/org/freedesktop/Local", * and SHOULD end with a capitalised term. Only one object may be exposed on each path at any one time, but an object * may be exposed on several paths at once. * @param object The object to export. @@ -354,6 +387,32 @@ public abstract class AbstractConnection objectTree.add(objectpath, eo, eo.introspectiondata); } } + /** + * Export an object as a fallback object. + * This object will have it's methods invoked for all paths starting + * with this object path. + * @param objectprefix The path below which the fallback handles calls. + * MUST be in slash-notation, like "/org/freedesktop/Local", + * @param object The object to export. + * @throws DBusException If the objectpath is incorrectly formatted, + */ + public void addFallback(String objectprefix, DBusInterface object) throws DBusException + { + if (null == objectprefix || "".equals(objectprefix)) + throw new DBusException("Must Specify an Object Path"); + if (!objectprefix.matches(OBJECT_REGEX)||objectprefix.length() > MAX_NAME_LENGTH) + throw new DBusException("Invalid object path ("+objectprefix+")"); + ExportedObject eo = new ExportedObject(object); + fallbackcontainer.add(objectprefix, eo); + } + /** + * Remove a fallback + * @param objectprefix The prefix to remove the fallback for. + */ + public void removeFallback(String objectprefix) + { + fallbackcontainer.remove(objectprefix); + } /** * Stop Exporting an object * @param objectpath The objectpath to stop exporting. @@ -631,6 +690,10 @@ public abstract class AbstractConnection eo = null; } + if (null == eo) { + eo = fallbackcontainer.get(m.getPath()); + } + if (null == eo) { try { queueOutgoing(new Error(m, new DBus.Error.UnknownObject(m.getPath()+" is not an object provided by this process."))); diff --git a/org/freedesktop/dbus/test/test.java b/org/freedesktop/dbus/test/test.java index 2eb16bd..e2dad6c 100644 --- a/org/freedesktop/dbus/test/test.java +++ b/org/freedesktop/dbus/test/test.java @@ -453,6 +453,7 @@ public class test serverconn.exportObject("/Test", tclass); serverconn.exportObject("/BadTest", tclass); serverconn.exportObject("/BadTest2", tclass2); + serverconn.addFallback("/FallbackTest", tclass); // explicitly unexport object serverconn.unExportObject("/BadTest"); @@ -609,7 +610,11 @@ public class test System.out.println("Remote Method Failed with: "+UO.getClass().getName()+" "+UO.getMessage()); } - System.out.println("Calling Method5--8"); + System.out.println("Calling Method6"); + tri = clientconn.getRemoteObject("foo.bar.Test", "/FallbackTest/0/1", TestRemoteInterface.class); + System.out.println("Got Fallback Name: "+tri.getName()); + + System.out.println("Calling Method7--9"); /** This gets a remote object matching our bus name and exported object path. */ TestRemoteInterface2 tri2 = clientconn.getRemoteObject("foo.bar.Test", "/Test", TestRemoteInterface2.class); System.out.print("Calling the other introspect method: "); -- cgit v1.2.3