summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO1
-rw-r--r--changelog2
-rw-r--r--debug.conf5
-rw-r--r--org/freedesktop/dbus/AbstractConnection.java36
-rw-r--r--org/freedesktop/dbus/DBusConnection.java13
-rw-r--r--org/freedesktop/dbus/DirectConnection.java12
-rw-r--r--org/freedesktop/dbus/ExportedObject.java6
-rw-r--r--org/freedesktop/dbus/ObjectTree.java12
-rw-r--r--org/freedesktop/dbus/test/test.java36
9 files changed, 103 insertions, 20 deletions
diff --git a/TODO b/TODO
index 21f4d0d..b1a0558 100644
--- a/TODO
+++ b/TODO
@@ -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
diff --git a/changelog b/changelog
index 8c2a19c..4e68933 100644
--- a/changelog
+++ b/changelog
@@ -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:
diff --git a/debug.conf b/debug.conf
index 4a6b81a..272642a 100644
--- a/debug.conf
+++ b/debug.conf
@@ -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: ");