diff options
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | changelog | 2 | ||||
-rw-r--r-- | debug.conf | 5 | ||||
-rw-r--r-- | org/freedesktop/dbus/AbstractConnection.java | 36 | ||||
-rw-r--r-- | org/freedesktop/dbus/DBusConnection.java | 13 | ||||
-rw-r--r-- | org/freedesktop/dbus/DirectConnection.java | 12 | ||||
-rw-r--r-- | org/freedesktop/dbus/ExportedObject.java | 6 | ||||
-rw-r--r-- | org/freedesktop/dbus/ObjectTree.java | 12 | ||||
-rw-r--r-- | org/freedesktop/dbus/test/test.java | 36 |
9 files changed, 103 insertions, 20 deletions
@@ -1,5 +1,4 @@ ** check that the blocking is correct on DBusAsyncReply and add an explicit timeout value - * only hold weak refs to user objects and reply correctly when they have gone * Javadoc * document that we handle Introspect for you * add header checks to daemon @@ -5,6 +5,8 @@ Version 2.4: yandex -dot- ru>) * Don't respond to Introspect/Ping except on the right interface (pointed out by Serkan Kaba <serkan_kaba -at- yahoo -dot- com>) + * Automatically unexport objects which go out of scope in the + parent program (don't hold a strong reference). Version 2.3.2: @@ -3,18 +3,19 @@ org.freedesktop.dbus.MessageWriter = INFO org.freedesktop.dbus.Message = ERR org.freedesktop.dbus.MethodCall = ERR org.freedesktop.dbus.MethodTuple = ERR -org.freedesktop.dbus.AbstractConnection = ERR +org.freedesktop.dbus.AbstractConnection = VERBOSE org.freedesktop.dbus.AbstractConnection$_thread = ERR org.freedesktop.dbus.AbstractConnection$_sender = ERR org.freedesktop.dbus.DirectConnection = ERR org.freedesktop.dbus.DBusConnection = ERR -org.freedesktop.dbus.AbstractConnection$1 = ERR +org.freedesktop.dbus.AbstractConnection$1 = VERBOSE org.freedesktop.dbus.DBusSignal = ERR org.freedesktop.dbus.EfficientQueue = ERR org.freedesktop.dbus.Transport = ERR org.freedesktop.dbus.Transport$SASL = ERR org.freedesktop.dbus.Transport$SASL$Command = ERR org.freedesktop.dbus.Marshalling = ERR +org.freedesktop.dbus.ObjectTree = VERBOSE org.freedesktop.dbus.BusAddress = ERR org.freedesktop.dbus.RemoteInvocationHandler = ERR org.freedesktop.dbus.test.cross_test_client = ERR diff --git a/org/freedesktop/dbus/AbstractConnection.java b/org/freedesktop/dbus/AbstractConnection.java index a66771b..6d45c69 100644 --- a/org/freedesktop/dbus/AbstractConnection.java +++ b/org/freedesktop/dbus/AbstractConnection.java @@ -191,6 +191,7 @@ public abstract class AbstractConnection static final int MAX_NAME_LENGTH = 255; protected Map<String,ExportedObject> exportedObjects; private ObjectTree objectTree; + private _globalhandler _globalhandlerreference; protected Map<DBusInterface,RemoteObject> importedObjects; protected Map<SignalTuple,Vector<DBusSigHandler>> handledSignals; protected EfficientMap pendingCalls; @@ -236,7 +237,10 @@ public abstract class AbstractConnection { exportedObjects = new HashMap<String,ExportedObject>(); importedObjects = new HashMap<DBusInterface,RemoteObject>(); - exportedObjects.put(null, new ExportedObject(new _globalhandler())); + _globalhandlerreference = new _globalhandler(); + synchronized (exportedObjects) { + exportedObjects.put(null, new ExportedObject(_globalhandlerreference)); + } handledSignals = new HashMap<SignalTuple,Vector<DBusSigHandler>>(); pendingCalls = new EfficientMap(PENDING_MAP_INITIAL_SIZE); outgoing = new EfficientQueue(PENDING_MAP_INITIAL_SIZE); @@ -300,9 +304,11 @@ public abstract class AbstractConnection String getExportedObject(DBusInterface i) throws DBusException { - for (String s: exportedObjects.keySet()) - if (exportedObjects.get(s).object.equals(i)) - return s; + synchronized (exportedObjects) { + for (String s: exportedObjects.keySet()) + if (i.equals(exportedObjects.get(s).object.get())) + return s; + } String s = importedObjects.get(i).objectpath; if (null != s) return s; @@ -345,7 +351,7 @@ public abstract class AbstractConnection throw new DBusException("Object already exported"); ExportedObject eo = new ExportedObject(object); exportedObjects.put(objectpath, eo); - objectTree.add(objectpath, object, eo.introspectiondata); + objectTree.add(objectpath, eo, eo.introspectiondata); } } /** @@ -356,6 +362,7 @@ public abstract class AbstractConnection { synchronized (exportedObjects) { exportedObjects.remove(objectpath); + objectTree.remove(objectpath); } } /** @@ -601,11 +608,17 @@ public abstract class AbstractConnection synchronized (exportedObjects) { eo = exportedObjects.get(null); } + if (null != eo && null == eo.object.get()) { + unExportObject(null); + eo = null; + } if (null != eo) { meth = eo.methods.get(new MethodTuple(m.getName(), m.getSig())); } if (null != meth) o = new _globalhandler(m.getPath()); + else + eo = null; } if (null == o) { // now check for specific exported functions @@ -613,6 +626,10 @@ public abstract class AbstractConnection synchronized (exportedObjects) { eo = exportedObjects.get(m.getPath()); } + if (null != eo && null == eo.object.get()) { + unExportObject(m.getPath()); + eo = null; + } if (null == eo) { try { @@ -620,6 +637,12 @@ public abstract class AbstractConnection } catch (DBusException DBe) {} return; } + if (Debug.debug) { + Debug.print(Debug.VERBOSE, "Searching for method "+m.getName()+" with signature "+m.getSig()); + Debug.print(Debug.VERBOSE, "List of methods on "+eo+":"); + for (MethodTuple mt: eo.methods.keySet()) + Debug.print(Debug.VERBOSE, " "+mt+" => "+eo.methods.get(mt)); + } meth = eo.methods.get(new MethodTuple(m.getName(), m.getSig())); if (null == meth) { try { @@ -627,7 +650,7 @@ public abstract class AbstractConnection } catch (DBusException DBe) {} return; } - o = eo.object; + o = eo.object.get(); } // now execute it @@ -663,6 +686,7 @@ public abstract class AbstractConnection } Object result; try { + if (Debug.debug) Debug.print(Debug.VERBOSE, "Invoking Method: "+me+" on "+ob+" with parameters "+Arrays.deepToString(m.getParameters())); result = me.invoke(ob, m.getParameters()); } catch (InvocationTargetException ITe) { if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, ITe.getCause()); diff --git a/org/freedesktop/dbus/DBusConnection.java b/org/freedesktop/dbus/DBusConnection.java index fcd2088..bc2e6c9 100644 --- a/org/freedesktop/dbus/DBusConnection.java +++ b/org/freedesktop/dbus/DBusConnection.java @@ -10,6 +10,8 @@ */ package org.freedesktop.dbus; +import java.lang.ref.WeakReference; + import java.lang.reflect.Proxy; import java.lang.reflect.Type; @@ -223,8 +225,15 @@ public class DBusConnection extends AbstractConnection DBusInterface getExportedObject(String source, String path) throws DBusException { - ExportedObject o = exportedObjects.get(path); - if (null != o) return o.object; + ExportedObject o = null; + synchronized (exportedObjects) { + o = exportedObjects.get(path); + } + if (null != o && null == o.object.get()) { + unExportObject(path); + o = null; + } + if (null != o) return o.object.get(); if (null == source) throw new DBusException("Not an object exported by this connection and no remote specified"); return dynamicProxy(source, path); } diff --git a/org/freedesktop/dbus/DirectConnection.java b/org/freedesktop/dbus/DirectConnection.java index 3fd2a2b..5254d54 100644 --- a/org/freedesktop/dbus/DirectConnection.java +++ b/org/freedesktop/dbus/DirectConnection.java @@ -10,6 +10,7 @@ */ package org.freedesktop.dbus; +import java.lang.ref.WeakReference; import java.lang.reflect.Proxy; import java.io.File; import java.io.IOException; @@ -137,8 +138,15 @@ public class DirectConnection extends AbstractConnection DBusInterface getExportedObject(String path) throws DBusException { - ExportedObject o = exportedObjects.get(path); - if (null != o) return o.object; + ExportedObject o = null; + synchronized (exportedObjects) { + o = exportedObjects.get(path); + } + if (null != o && null == o.object.get()) { + unExportObject(path); + o = null; + } + if (null != o) return o.object.get(); return dynamicProxy(path); } diff --git a/org/freedesktop/dbus/ExportedObject.java b/org/freedesktop/dbus/ExportedObject.java index a60ab79..51883c3 100644 --- a/org/freedesktop/dbus/ExportedObject.java +++ b/org/freedesktop/dbus/ExportedObject.java @@ -10,6 +10,8 @@ */ package org.freedesktop.dbus; +import java.lang.ref.WeakReference; + import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; @@ -134,11 +136,11 @@ class ExportedObject return m; } Map<MethodTuple,Method> methods; - DBusInterface object; + WeakReference<DBusInterface> object; String introspectiondata; public ExportedObject(DBusInterface object) throws DBusException { - this.object = object; + this.object = new WeakReference<DBusInterface>(object); introspectiondata = ""; methods = getExportedMethods(object.getClass()); introspectiondata += diff --git a/org/freedesktop/dbus/ObjectTree.java b/org/freedesktop/dbus/ObjectTree.java index 6f932c0..4c8932c 100644 --- a/org/freedesktop/dbus/ObjectTree.java +++ b/org/freedesktop/dbus/ObjectTree.java @@ -10,6 +10,8 @@ */ package org.freedesktop.dbus; +import cx.ath.matthew.debug.Debug; + import java.util.regex.Pattern; /** @@ -19,7 +21,7 @@ class ObjectTree class TreeNode { String name; - DBusInterface object; + ExportedObject object; String data; TreeNode right; TreeNode down; @@ -27,7 +29,7 @@ class ObjectTree { this.name = name; } - public TreeNode(String name, DBusInterface object, String data) + public TreeNode(String name, ExportedObject object, String data) { this.name = name; this.object = object; @@ -69,7 +71,7 @@ class ObjectTree return recursiveFind(current.right, path); } } - private TreeNode recursiveAdd(TreeNode current, String path, DBusInterface object, String data) + private TreeNode recursiveAdd(TreeNode current, String path, ExportedObject object, String data) { String[] elements = slashpattern.split(path, 2); // this is us or a parent node @@ -106,12 +108,14 @@ class ObjectTree } return current; } - public void add(String path, DBusInterface object, String data) + public void add(String path, ExportedObject object, String data) { + if (Debug.debug) Debug.print(Debug.DEBUG, "Adding "+path+" to object tree"); root = recursiveAdd(root, path, object, data); } public void remove(String path) { + if (Debug.debug) Debug.print(Debug.DEBUG, "Removing "+path+" from object tree"); TreeNode t = recursiveFind(root, path); t.object = null; t.data = null; diff --git a/org/freedesktop/dbus/test/test.java b/org/freedesktop/dbus/test/test.java index f2f4c06..2eb16bd 100644 --- a/org/freedesktop/dbus/test/test.java +++ b/org/freedesktop/dbus/test/test.java @@ -448,8 +448,22 @@ public class test System.out.println("Listening for Method Calls"); testclass tclass = new testclass(serverconn); + testclass tclass2 = new testclass(serverconn); /** This exports an instance of the test class as the object /Test. */ serverconn.exportObject("/Test", tclass); + serverconn.exportObject("/BadTest", tclass); + serverconn.exportObject("/BadTest2", tclass2); + + // explicitly unexport object + serverconn.unExportObject("/BadTest"); + // implicitly unexport object + tclass2 = null; + System.gc(); + System.runFinalization(); + System.gc(); + System.runFinalization(); + System.gc(); + System.runFinalization(); System.out.println("Sending Signal"); /** This creates an instance of the Test Signal, with the given object path, signal name and parameters, and broadcasts in on the Bus. */ @@ -574,8 +588,28 @@ public class test } catch (UnknownObject UO) { System.out.println("Remote Method Failed with: "+UO.getClass().getName()+" "+UO.getMessage()); } + + /** Try and call an explicitly unexported object */ + try { + System.out.println("Calling Method4"); + tri = clientconn.getRemoteObject("foo.bar.Test", "/BadTest", TestRemoteInterface.class); + System.out.println("Got Remote Name: "+tri.getName()); + test.fail("Method Execution should have failed"); + } catch (UnknownObject UO) { + System.out.println("Remote Method Failed with: "+UO.getClass().getName()+" "+UO.getMessage()); + } + + /** Try and call an implicitly unexported object */ + try { + System.out.println("Calling Method5"); + tri = clientconn.getRemoteObject("foo.bar.Test", "/BadTest2", TestRemoteInterface.class); + System.out.println("Got Remote Name: "+tri.getName()); + test.fail("Method Execution should have failed"); + } catch (UnknownObject UO) { + System.out.println("Remote Method Failed with: "+UO.getClass().getName()+" "+UO.getMessage()); + } - System.out.println("Calling Method4/5/6/7"); + System.out.println("Calling Method5--8"); /** 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: "); |