summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile13
-rw-r--r--TODO6
-rw-r--r--changelog7
-rw-r--r--dbus-java.tex10
-rw-r--r--org/freedesktop/dbus/AbstractConnection.java761
-rw-r--r--org/freedesktop/dbus/ArrayFrob.java2
-rw-r--r--org/freedesktop/dbus/DBusAsyncReply.java6
-rw-r--r--org/freedesktop/dbus/DBusConnection.java714
-rw-r--r--org/freedesktop/dbus/DBusMatchRule.java8
-rw-r--r--org/freedesktop/dbus/DBusSignal.java14
-rw-r--r--org/freedesktop/dbus/DirectConnection.java210
-rw-r--r--org/freedesktop/dbus/EfficientQueue.java7
-rw-r--r--org/freedesktop/dbus/Error.java18
-rw-r--r--org/freedesktop/dbus/ExportedObject.java11
-rw-r--r--org/freedesktop/dbus/Marshalling.java126
-rw-r--r--org/freedesktop/dbus/Message.java25
-rw-r--r--org/freedesktop/dbus/MessageReader.java4
-rw-r--r--org/freedesktop/dbus/MethodCall.java9
-rw-r--r--org/freedesktop/dbus/MethodReturn.java11
-rw-r--r--org/freedesktop/dbus/RemoteInvocationHandler.java21
-rw-r--r--org/freedesktop/dbus/RemoteObject.java14
-rw-r--r--org/freedesktop/dbus/Transport.java91
-rw-r--r--org/freedesktop/dbus/Variant.java6
-rw-r--r--org/freedesktop/dbus/exceptions/FatalDBusException.java20
-rw-r--r--org/freedesktop/dbus/exceptions/InternalMessageException.java2
-rw-r--r--org/freedesktop/dbus/exceptions/NotConnected.java2
-rw-r--r--org/freedesktop/dbus/test/TestRemoteInterface.java2
-rw-r--r--org/freedesktop/dbus/test/test.java13
-rw-r--r--org/freedesktop/dbus/test/test_p2p_client.java42
-rw-r--r--org/freedesktop/dbus/test/test_p2p_server.java72
30 files changed, 1401 insertions, 846 deletions
diff --git a/Makefile b/Makefile
index 8083cbf..ce038bf 100644
--- a/Makefile
+++ b/Makefile
@@ -97,7 +97,7 @@ doc/dbus-java/index.html: dbus-java.tex .doc
rm -f doc/dbus-java/*{4ct,4tc,aux,dvi,idv,lg,log,tmp,xref}
cp doc/dbus-java/dbus-java.html doc/dbus-java/index.html
doc/api/index.html: $(SRCDIR)/*.java $(SRCDIR)/dbus/*.java .doc
- $(JAVADOC) -quiet -author -link http://java.sun.com/j2se/1.5.0/docs/api/ -d doc/api $(SRCDIR)/*.java $(SRCDIR)/dbus/*.java
+ $(JAVADOC) -quiet -author -link http://java.sun.com/j2se/1.5.0/docs/api/ -classpath $(JAVAUNIXJARDIR)/unix.jar:$(JAVAUNIXJARDIR)/hexdump.jar:$(JAVAUNIXJARDIR)/debug-$(DEBUG).jar -d doc/api $(SRCDIR)/*.java $(SRCDIR)/dbus/*.java $(SRCDIR)/dbus/{types,exceptions}/*.java
%.1: %.sgml
docbook-to-man $< > $@
@@ -114,6 +114,12 @@ cross-test-server: libdbus-java-$(VERSION).jar dbus-java-test-$(VERSION).jar
cross-test-client: libdbus-java-$(VERSION).jar dbus-java-test-$(VERSION).jar
$(JAVA) $(JFLAGS) $(CPFLAG) $(CLASSPATH):$(JAVAUNIXJARDIR)/unix.jar:$(JAVAUNIXJARDIR)/hexdump.jar:$(JAVAUNIXJARDIR)/debug-$(DEBUG).jar:libdbus-java-$(VERSION).jar:dbus-java-test-$(VERSION).jar org.freedesktop.dbus.test.cross_test_client
+peer-server: libdbus-java-$(VERSION).jar dbus-java-test-$(VERSION).jar
+ $(JAVA) $(JFLAGS) $(CPFLAG) $(CLASSPATH):$(JAVAUNIXJARDIR)/unix.jar:$(JAVAUNIXJARDIR)/hexdump.jar:$(JAVAUNIXJARDIR)/debug-$(DEBUG).jar:libdbus-java-$(VERSION).jar:dbus-java-test-$(VERSION).jar org.freedesktop.dbus.test.test_p2p_server
+
+peer-client: libdbus-java-$(VERSION).jar dbus-java-test-$(VERSION).jar
+ $(JAVA) $(JFLAGS) $(CPFLAG) $(CLASSPATH):$(JAVAUNIXJARDIR)/unix.jar:$(JAVAUNIXJARDIR)/hexdump.jar:$(JAVAUNIXJARDIR)/debug-$(DEBUG).jar:libdbus-java-$(VERSION).jar:dbus-java-test-$(VERSION).jar org.freedesktop.dbus.test.test_p2p_client
+
two-part-server: libdbus-java-$(VERSION).jar dbus-java-test-$(VERSION).jar
$(JAVA) $(JFLAGS) $(CPFLAG) $(CLASSPATH):$(JAVAUNIXJARDIR)/unix.jar:$(JAVAUNIXJARDIR)/hexdump.jar:$(JAVAUNIXJARDIR)/debug-$(DEBUG).jar:libdbus-java-$(VERSION).jar:dbus-java-test-$(VERSION).jar org.freedesktop.dbus.test.two_part_test_server
@@ -145,6 +151,11 @@ internal-cross-test: libdbus-java-$(VERSION).jar dbus-java-test-$(VERSION).jar
$(MAKE) -s cross-test-client | tee client.log ;\
kill $$(cat pid) ; )
+peer-to-peer-test: libdbus-java-$(VERSION).jar dbus-java-test-$(VERSION).jar
+ ( $(MAKE) DBUS_JAVA_FLOATS=true -s peer-server 2>&1 | tee server.log &\
+ sleep 1;\
+ $(MAKE) DBUS_JAVA_FLOATS=true -s peer-client 2>&1 | tee client.log )
+
two-part-test: libdbus-java-$(VERSION).jar dbus-java-test-$(VERSION).jar
( dbus-daemon --config-file=tmp-session.conf --print-pid --print-address=5 --fork >pid 5>address ; \
export DBUS_SESSION_BUS_ADDRESS=$$(cat address) ;\
diff --git a/TODO b/TODO
index 7ac8332..6051045 100644
--- a/TODO
+++ b/TODO
@@ -1,10 +1,12 @@
- * test floats and make them degrade nicely
+ * document string comparisons
+ * document peer2peer
+ * document low level
* autolaunch
* dbus-sha-1 auth
* test tcp
* write a bus daemon
- * peer2peer
* test on windbus
+ * autodetection of float support
* allow 'virtual' object handlers, so that all object paths under a certain hierarchy are handled by the same object
* fix dbus-viewer to recurse on paths
* extend dbus-viewer to make calls
diff --git a/changelog b/changelog
index 102bffb..be0e6d6 100644
--- a/changelog
+++ b/changelog
@@ -16,6 +16,13 @@ Version 2.0:
associated with this connection.
* Access to the low-level API added.
* Change all documentation to refer to 'implementation' not 'binding'
+ * Add peer 2 peer support with DirectConnection class
+ * add peer to peer test
+ * split some code from DBusConnection into common super-class
+ AbstractConnection
+ * Support float ('f') type with tests
+ * Degrade floats to doubles when DBUS_JAVA_FLOATS is not set
+ * add DBus.Peer interface to standard introspection data
Version 1.13:
diff --git a/dbus-java.tex b/dbus-java.tex
index 36e493a..a433e91 100644
--- a/dbus-java.tex
+++ b/dbus-java.tex
@@ -641,11 +641,11 @@ Type$[$~$]$ & DBUS\_TYPE\_SIGNATURE \\
\subsubsection{float}
Currently the D-Bus reference implementation does not support a native
-single-precision floating point type. Along with the C# implementation of the
-protocol, the Java implementation supports this extension to the protocol. When
-communicating with the reference implementation, however, these will all be
-converted to doubles for transmission on the wire. In the case of systems
-supporting this extension, the type code `f' is used for floats.
+single-precision floating point type. Along with the C\# implementation of the
+protocol, the Java implementation supports this extension to the protocol. By
+default, however, the library operates in compatibility mode and converts all
+floats to the double type. To disable compatibility mode export the environment
+variable {\tt DBUS\_JAVA\_FLOATS=true}.
\section{Annotations}
diff --git a/org/freedesktop/dbus/AbstractConnection.java b/org/freedesktop/dbus/AbstractConnection.java
new file mode 100644
index 0000000..1cb3421
--- /dev/null
+++ b/org/freedesktop/dbus/AbstractConnection.java
@@ -0,0 +1,761 @@
+/*
+ D-Bus Java Implementation
+ Copyright (c) 2005-2006 Matthew Johnson
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of either the GNU General Public License Version 2 or the
+ Academic Free Licence Version 2.1.
+
+ Full licence texts are included in the COPYING file with this program.
+*/
+package org.freedesktop.dbus;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+import java.io.File;
+import java.io.IOException;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Vector;
+
+import java.util.regex.Pattern;
+
+import org.freedesktop.DBus;
+import org.freedesktop.dbus.exceptions.NotConnected;
+import org.freedesktop.dbus.exceptions.DBusException;
+import org.freedesktop.dbus.exceptions.DBusExecutionException;
+import org.freedesktop.dbus.exceptions.FatalDBusException;
+import org.freedesktop.dbus.exceptions.FatalException;
+import org.freedesktop.dbus.exceptions.NonFatalException;
+
+import cx.ath.matthew.debug.Debug;
+
+
+/** Handles a connection to DBus.
+ */
+public abstract class AbstractConnection
+{
+ protected class _thread extends Thread
+ {
+ public _thread()
+ {
+ setName("DBusConnection");
+ }
+ public void run()
+ {
+ try {
+ Message m = null;
+ while (_run) {
+ m = null;
+
+ // read from the wire
+ try {
+ // this blocks on outgoing being non-empty or a message being available.
+ m = readIncoming(TIMEOUT, outgoing);
+ if (m != null) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Got Incoming Message: "+m);
+ synchronized (this) { notifyAll(); }
+
+ if (m instanceof DBusSignal)
+ handleMessage((DBusSignal) m);
+ else if (m instanceof MethodCall)
+ handleMessage((MethodCall) m);
+ else if (m instanceof MethodReturn)
+ handleMessage((MethodReturn) m);
+ else if (m instanceof Error)
+ handleMessage((Error) m);
+
+ m = null;
+ }
+ } catch (Exception e) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (e instanceof FatalException) {
+ try {
+ handleMessage(new org.freedesktop.DBus.Local.Disconnected("/"));
+ } catch (Exception ee) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, ee);
+ }
+ disconnect();
+ }
+ }
+
+ // write to the wire
+ if (null != outgoing) synchronized (outgoing) {
+ if (!outgoing.isEmpty())
+ m = outgoing.remove(); }
+ while (null != m) {
+ sendMessage(m);
+ m = null;
+ if (null != outgoing) synchronized (outgoing) {
+ if (!outgoing.isEmpty())
+ m = outgoing.remove(); }
+ }
+ }
+ if (null != outgoing) synchronized (outgoing) {
+ if (!outgoing.isEmpty())
+ m = outgoing.remove();
+ }
+ while (null != m) {
+ sendMessage(m);
+ m = null;
+ if (null != outgoing) synchronized (outgoing) {
+ if (!outgoing.isEmpty())
+ m = outgoing.remove(); }
+ }
+ synchronized (this) { notifyAll(); }
+ } catch (NotConnected NC) {}
+ }
+ }
+ private class _globalhandler implements org.freedesktop.DBus.Peer, org.freedesktop.DBus.Introspectable
+ {
+ private String objectpath;
+ public _globalhandler()
+ {
+ this.objectpath = null;
+ }
+ public _globalhandler(String objectpath)
+ {
+ this.objectpath = objectpath;
+ }
+ public boolean isRemote() { return false; }
+ public void Ping() { return; }
+ public String Introspect()
+ {
+ String intro = objectTree.Introspect(objectpath);
+ if (null == intro)
+ throw new DBus.Error.UnknownObject("Introspecting on non-existant object");
+ else return
+ "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "+
+ "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"+intro;
+ }
+ }
+ protected class _workerthread extends Thread
+ {
+ private boolean _run = true;
+ public void halt()
+ {
+ _run = false;
+ }
+ public void run()
+ {
+ while (_run) {
+ Runnable r = null;
+ synchronized (runnables) {
+ while (runnables.size() == 0 && _run)
+ try { runnables.wait(); } catch (InterruptedException Ie) {}
+ if (runnables.size() > 0)
+ r = runnables.removeFirst();
+ }
+ if (null != r) r.run();
+ }
+ }
+ }
+ /**
+ * Timeout in ms on checking the BUS for incoming messages and sending outgoing messages
+ */
+ private static final int TIMEOUT = 1;
+ /** Initial size of the pending calls map */
+ private static final int PENDING_MAP_INITIAL_SIZE = 10;
+ static final String BUSNAME_REGEX = "^[-_a-zA-Z][-_a-zA-Z0-9]*(\\.[-_a-zA-Z][-_a-zA-Z0-9]*)*$";
+ static final String CONNID_REGEX = "^:[0-9]*\\.[0-9]*$";
+ static final String OBJECT_REGEX = "^/([-_a-zA-Z0-9]+(/[-_a-zA-Z0-9]+)*)?$";
+ static final byte THREADCOUNT = 4;
+ static final int MAX_ARRAY_LENGTH = 67108864;
+ static final int MAX_NAME_LENGTH = 255;
+ protected Map<String,ExportedObject> exportedObjects;
+ private ObjectTree objectTree;
+ protected Map<DBusInterface,RemoteObject> importedObjects;
+ protected Map<SignalTuple,Vector<DBusSigHandler>> handledSignals;
+ protected EfficientMap pendingCalls;
+ protected LinkedList<Runnable> runnables;
+ protected LinkedList<_workerthread> workers;
+ protected boolean _run;
+ EfficientQueue outgoing;
+ LinkedList<Error> pendingErrors;
+ private static final Map<Thread,DBusCallInfo> infomap = new HashMap<Thread,DBusCallInfo>();
+ protected _thread thread;
+ protected Transport transport;
+ protected String addr;
+ static final Pattern dollar_pattern = Pattern.compile("[$]");
+ public static final boolean EXCEPTION_DEBUG;
+ static final boolean FLOAT_SUPPORT;
+ static {
+ FLOAT_SUPPORT = (null != System.getenv("DBUS_JAVA_FLOATS"));
+ EXCEPTION_DEBUG = (null != System.getenv("DBUS_JAVA_EXCEPTION_DEBUG"));
+ if (EXCEPTION_DEBUG) {
+ Debug.print("Debugging of internal exceptions enabled");
+ Debug.setThrowableTraces(true);
+ }
+ if (Debug.debug) {
+ File f = new File("debug.conf");
+ if (f.exists()) {
+ Debug.print("Loading debug config file: "+f);
+ try {
+ Debug.loadConfig(f);
+ } catch (IOException IOe) {}
+ } else {
+ Properties p = new Properties();
+ p.setProperty("ALL", "INFO");
+ Debug.print("debug config file "+f+" does not exist, not loading.");
+ }
+ Debug.setHexDump(true);
+ }
+ }
+
+ protected AbstractConnection(String address) throws DBusException
+ {
+ exportedObjects = new HashMap<String,ExportedObject>();
+ importedObjects = new HashMap<DBusInterface,RemoteObject>();
+ exportedObjects.put(null, new ExportedObject(new _globalhandler()));
+ handledSignals = new HashMap<SignalTuple,Vector<DBusSigHandler>>();
+ pendingCalls = new EfficientMap(PENDING_MAP_INITIAL_SIZE);
+ outgoing = new EfficientQueue(PENDING_MAP_INITIAL_SIZE);
+ pendingErrors = new LinkedList<Error>();
+ runnables = new LinkedList<Runnable>();
+ workers = new LinkedList<_workerthread>();
+ objectTree = new ObjectTree();
+ synchronized (workers) {
+ for (int i = 0; i < THREADCOUNT; i++) {
+ _workerthread t = new _workerthread();
+ t.start();
+ workers.add(t);
+ }
+ }
+ _run = true;
+ addr = address;
+ }
+
+ protected void listen()
+ {
+ // start listening
+ thread = new _thread();
+ thread.start();
+ }
+
+ /**
+ * Change the number of worker threads to receive method calls and handle signals.
+ * Default is 4 threads
+ * @param newcount The new number of worker Threads to use.
+ */
+ public void changeThreadCount(byte newcount)
+ {
+ synchronized (workers) {
+ if (workers.size() > newcount) {
+ int n = workers.size() - newcount;
+ for (int i = 0; i < n; i++) {
+ _workerthread t = workers.removeFirst();
+ t.halt();
+ }
+ } else if (workers.size() < newcount) {
+ int n = newcount-workers.size();
+ for (int i = 0; i < n; i++) {
+ _workerthread t = new _workerthread();
+ t.start();
+ workers.add(t);
+ }
+ }
+ }
+ }
+ private void addRunnable(Runnable r)
+ {
+ synchronized(runnables) {
+ runnables.add(r);
+ runnables.notifyAll();
+ }
+ }
+
+ String getExportedObject(DBusInterface i) throws DBusException
+ {
+ for (String s: exportedObjects.keySet())
+ if (exportedObjects.get(s).object.equals(i))
+ return s;
+
+ String s = importedObjects.get(i).objectpath;
+ if (null != s) return s;
+
+ throw new DBusException("Not an object exported or imported by this connection");
+ }
+
+ abstract DBusInterface getExportedObject(String source, String path) throws DBusException;
+
+ /**
+ * Returns a structure with information on the current method call.
+ * @return the DBusCallInfo for this method call, or null if we are not in a method call.
+ */
+ public static DBusCallInfo getCallInfo()
+ {
+ DBusCallInfo info;
+ synchronized (infomap) {
+ info = infomap.get(Thread.currentThread());
+ }
+ return info;
+ }
+
+ /**
+ * 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",
+ * 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.
+ * @throws DBusException If the objectpath is already exporting an object.
+ * or if objectpath is incorrectly formatted,
+ */
+ public void exportObject(String objectpath, DBusInterface object) throws DBusException
+ {
+ if (!objectpath.matches(OBJECT_REGEX)||objectpath.length() > MAX_NAME_LENGTH)
+ throw new DBusException("Invalid object path ("+objectpath+")");
+ if (null == objectpath || "".equals(objectpath))
+ throw new DBusException("Must Specify an Object Path");
+ synchronized (exportedObjects) {
+ if (null != exportedObjects.get(objectpath))
+ throw new DBusException("Object already exported");
+ ExportedObject eo = new ExportedObject(object);
+ exportedObjects.put(objectpath, eo);
+ objectTree.add(objectpath, object, eo.introspectiondata);
+ }
+ }
+ /**
+ * Stop Exporting an object
+ * @param objectpath The objectpath to stop exporting.
+ */
+ public void unExportObject(String objectpath)
+ {
+ synchronized (exportedObjects) {
+ exportedObjects.remove(objectpath);
+ }
+ }
+ /**
+ * Return a reference to a remote object.
+ * This method will resolve the well known name (if given) to a unique bus name when you call it.
+ * This means that if a well known name is released by one process and acquired by another calls to
+ * objects gained from this method will continue to operate on the original process.
+ * @param busname The bus name to connect to. Usually a well known bus name in dot-notation (such as "org.freedesktop.local")
+ * or may be a DBus address such as ":1-16".
+ * @param objectpath The path on which the process is exporting the object.$
+ * @param type The interface they are exporting it on. This type must have the same full class name and exposed method signatures
+ * as the interface the remote object is exporting.
+ * @return A reference to a remote object.
+ * @throws ClassCastException If type is not a sub-type of DBusInterface
+ * @throws DBusException If busname or objectpath are incorrectly formatted or type is not in a package.
+ */
+ /**
+ * Send a signal.
+ * @param signal The signal to send.
+ */
+ public void sendSignal(DBusSignal signal)
+ {
+ if (null == outgoing) return;
+ synchronized (outgoing) {
+ outgoing.add(signal); }
+ }
+ /**
+ * Remove a Signal Handler.
+ * Stops listening for this signal.
+ * @param type The signal to watch for.
+ * @throws DBusException If listening for the signal on the bus failed.
+ * @throws ClassCastException If type is not a sub-type of DBusSignal.
+ */
+ public <T extends DBusSignal> void removeSigHandler(Class<T> type, DBusSigHandler<T> handler) throws DBusException
+ {
+ if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException("Not A DBus Signal");
+ removeSigHandler(new DBusMatchRule(type), handler);
+ }
+ /**
+ * Remove a Signal Handler.
+ * Stops listening for this signal.
+ * @param type The signal to watch for.
+ * @param object The object emitting the signal.
+ * @throws DBusException If listening for the signal on the bus failed.
+ * @throws ClassCastException If type is not a sub-type of DBusSignal.
+ */
+ public <T extends DBusSignal> void removeSigHandler(Class<T> type, DBusInterface object, DBusSigHandler<T> handler) throws DBusException
+ {
+ if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException("Not A DBus Signal");
+ String objectpath = importedObjects.get(object).objectpath;
+ if (!objectpath.matches(OBJECT_REGEX)||objectpath.length() > MAX_NAME_LENGTH)
+ throw new DBusException("Invalid object path ("+objectpath+")");
+ removeSigHandler(new DBusMatchRule(type, null, objectpath), handler);
+ }
+
+ protected abstract <T extends DBusSignal> void removeSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException;
+ /**
+ * Add a Signal Handler.
+ * Adds a signal handler to call when a signal is received which matches the specified type and name.
+ * @param type The signal to watch for.
+ * @param handler The handler to call when a signal is received.
+ * @throws DBusException If listening for the signal on the bus failed.
+ * @throws ClassCastException If type is not a sub-type of DBusSignal.
+ */
+ public <T extends DBusSignal> void addSigHandler(Class<T> type, DBusSigHandler<T> handler) throws DBusException
+ {
+ if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException("Not A DBus Signal");
+ addSigHandler(new DBusMatchRule(type), handler);
+ }
+ /**
+ * Add a Signal Handler.
+ * Adds a signal handler to call when a signal is received which matches the specified type, name and object.
+ * @param type The signal to watch for.
+ * @param object The object from which the signal will be emitted
+ * @param handler The handler to call when a signal is received.
+ * @throws DBusException If listening for the signal on the bus failed.
+ * @throws ClassCastException If type is not a sub-type of DBusSignal.
+ */
+ public <T extends DBusSignal> void addSigHandler(Class<T> type, DBusInterface object, DBusSigHandler<T> handler) throws DBusException
+ {
+ if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException("Not A DBus Signal");
+ String objectpath = importedObjects.get(object).objectpath;
+ if (!objectpath.matches(OBJECT_REGEX)||objectpath.length() > MAX_NAME_LENGTH)
+ throw new DBusException("Invalid object path ("+objectpath+")");
+ addSigHandler(new DBusMatchRule(type, null, objectpath), handler);
+ }
+
+ protected abstract <T extends DBusSignal> void addSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException;
+
+ protected void addSigHandlerWithoutMatch(Class signal, DBusSigHandler handler) throws DBusException
+ {
+ DBusMatchRule rule = new DBusMatchRule(signal);
+ SignalTuple key = new SignalTuple(rule.getInterface(), rule.getMember(), rule.getObject(), rule.getSource());
+ synchronized (handledSignals) {
+ Vector<DBusSigHandler> v = handledSignals.get(key);
+ if (null == v) {
+ v = new Vector<DBusSigHandler>();
+ v.add(handler);
+ handledSignals.put(key, v);
+ } else
+ v.add(handler);
+ }
+ }
+
+ /**
+ * Disconnect from the Bus.
+ */
+ public void disconnect()
+ {
+ // run all pending tasks.
+ while (runnables.size() > 0)
+ synchronized (runnables) {
+ runnables.notifyAll();
+ }
+
+ // stop the main thread
+ _run = false;
+
+ // disconnect from the trasport layer
+ try {
+ transport.disconnect();
+ } catch (IOException IOe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOe);
+ }
+
+ // stop all the workers
+ synchronized(workers) {
+ for (_workerthread t: workers)
+ t.halt();
+ }
+
+ // make sure none are blocking on the runnables queue still
+ synchronized (runnables) {
+ runnables.notifyAll();
+ }
+ }
+
+ public void finalize()
+ {
+ disconnect();
+ }
+ /**
+ * Return any DBus error which has been received.
+ * @return A DBusExecutionException, or null if no error is pending.
+ */
+ public DBusExecutionException getError()
+ {
+ synchronized (pendingErrors) {
+ if (pendingErrors.size() == 0) return null;
+ else
+ return pendingErrors.removeFirst().getException();
+ }
+ }
+
+ /**
+ * Call a method asynchronously and get a handle with which to get the reply.
+ * @param object The remote object on which to call the method.
+ * @param m The name of the method on the interface to call.
+ * @param parameters The parameters to call the method with.
+ * @return A handle to the call.
+ */
+ public DBusAsyncReply callMethodAsync(DBusInterface object, String m, Object... parameters)
+ {
+ Class[] types = new Class[parameters.length];
+ for (int i = 0; i < parameters.length; i++)
+ types[i] = parameters[i].getClass();
+ RemoteObject ro = importedObjects.get(object);
+
+ try {
+ Method me;
+ if (null == ro.iface)
+ me = object.getClass().getMethod(m, types);
+ else
+ me = ro.iface.getMethod(m, types);
+ return (DBusAsyncReply) RemoteInvocationHandler.executeRemoteMethod(ro, me, this, true, parameters);
+ } catch (DBusExecutionException DBEe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
+ throw DBEe;
+ } catch (Exception e) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ throw new DBusExecutionException(e.getMessage());
+ }
+ }
+
+ private void handleMessage(final MethodCall m) throws DBusException
+ {
+ if (Debug.debug) Debug.print(Debug.ERR, "Handling incoming method call: "+m);
+ // get the method signature
+ Object[] params = m.getParameters();
+
+ ExportedObject eo = null;
+ Method meth = null;
+ Object o;
+
+ synchronized (exportedObjects) {
+ eo = exportedObjects.get(null);
+ }
+ if (null != eo) {
+ meth = eo.methods.get(new MethodTuple(m.getName(), m.getSig()));
+ }
+ if (null != meth)
+ o = new _globalhandler(m.getPath());
+
+ else {
+ // now check for specific exported functions
+
+ synchronized (exportedObjects) {
+ eo = exportedObjects.get(m.getPath());
+ }
+
+ if (null == eo) {
+ try {
+ if (null != outgoing) synchronized (outgoing) {
+ outgoing.add(new Error(m, new DBus.Error.UnknownObject(m.getPath()+" is not an object provided by this process."))); }
+ } catch (DBusException DBe) {}
+ return;
+ }
+ meth = eo.methods.get(new MethodTuple(m.getName(), m.getSig()));
+ if (null == meth) {
+ try {
+ if (null != outgoing) synchronized (outgoing) {
+ outgoing.add(new Error(m, new DBus.Error.UnknownMethod("The method `"+m.getInterface()+"."+m.getName()+"' does not exist on this object."))); }
+ } catch (DBusException DBe) {}
+ return;
+ }
+ o = eo.object;
+ }
+
+ // now execute it
+ final Method me = meth;
+ final Object ob = o;
+ final EfficientQueue outqueue = outgoing;
+ final boolean noreply = (1 == (m.getFlags() & Message.Flags.NO_REPLY_EXPECTED));
+ final DBusCallInfo info = new DBusCallInfo(m);
+ final AbstractConnection conn = this;
+ addRunnable(new Runnable()
+ {
+ public void run()
+ {
+ if (Debug.debug) Debug.print(Debug.DEBUG, "Running method "+me+" for remote call");
+ try {
+ Type[] ts = me.getGenericParameterTypes();
+ m.setArgs(Marshalling.deSerializeParameters(m.getParameters(), ts, conn));
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Deserialised "+Arrays.deepToString(m.getParameters())+" to types "+Arrays.deepToString(ts));
+ } catch (Exception e) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ try {
+ synchronized (outqueue) {
+ outqueue.add(new Error(m, new DBus.Error.UnknownMethod("Failure in de-serializing message ("+e+")")));
+ }
+ } catch (DBusException DBe) {}
+ return;
+ }
+
+ try {
+ synchronized (infomap) {
+ infomap.put(Thread.currentThread(), info);
+ }
+ Object result;
+ try {
+ result = me.invoke(ob, m.getParameters());
+ } catch (InvocationTargetException ITe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, ITe.getCause());
+ throw ITe.getCause();
+ }
+ synchronized (infomap) {
+ infomap.remove(Thread.currentThread());
+ }
+ if (!noreply) {
+ MethodReturn reply;
+ if (Void.TYPE.equals(me.getReturnType()))
+ reply = new MethodReturn(m, null);
+ else {
+ StringBuffer sb = new StringBuffer();
+ for (String s: Marshalling.getDBusType(me.getGenericReturnType()))
+ sb.append(s);
+ Object[] nr = Marshalling.convertParameters(new Object[] { result }, new Type[] {me.getGenericReturnType()}, conn);
+
+ reply = new MethodReturn(m, sb.toString(),nr);
+ }
+ synchronized (outqueue) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Queuing reply");
+ outqueue.add(reply);
+ }
+ }
+ } catch (DBusExecutionException DBEe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
+ try {
+ synchronized (outqueue) {
+ outqueue.add(new Error(m, DBEe));
+ }
+ } catch (DBusException DBe) {}
+ } catch (Throwable e) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ try {
+ synchronized (outqueue) {
+ outqueue.add(new Error(m, new DBusExecutionException("Error Executing Method "+m.getInterface()+"."+m.getName()+": "+e.getMessage())));
+ }
+ } catch (DBusException DBe) {}
+ }
+ }
+ });
+ }
+ @SuppressWarnings({"unchecked","deprecation"})
+ private void handleMessage(final DBusSignal s)
+ {
+ if (Debug.debug) Debug.print(Debug.ERR, "Handling incoming signal: "+s);
+ Vector<DBusSigHandler> v = new Vector<DBusSigHandler>();
+ synchronized(handledSignals) {
+ Vector<DBusSigHandler> t;
+ t = handledSignals.get(new SignalTuple(s.getInterface(), s.getName(), null, null));
+ if (null != t) v.addAll(t);
+ t = handledSignals.get(new SignalTuple(s.getInterface(), s.getName(), s.getPath(), null));
+ if (null != t) v.addAll(t);
+ t = handledSignals.get(new SignalTuple(s.getInterface(), s.getName(), null, s.getSource()));
+ if (null != t) v.addAll(t);
+ t = handledSignals.get(new SignalTuple(s.getInterface(), s.getName(), s.getPath(), s.getSource()));
+ if (null != t) v.addAll(t);
+ }
+ if (0 == v.size()) return;
+ final EfficientQueue outqueue = outgoing;
+ final AbstractConnection conn = this;
+ for (final DBusSigHandler h: v)
+ addRunnable(new Runnable() { public void run() {
+ {
+ try {
+ DBusSignal rs;
+ if (s instanceof DBusSignal.internalsig || s.getClass().equals(DBusSignal.class))
+ rs = s.createReal(conn);
+ else
+ rs = s;
+ h.handle(rs);
+ } catch (DBusException DBe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
+ try {
+ synchronized (outqueue) {
+ outqueue.add(new Error(s, new DBusExecutionException("Error handling signal "+s.getInterface()+"."+s.getName()+": "+DBe.getMessage())));
+ }
+ } catch (DBusException DBe2) {}
+ }
+ }
+ } });
+ }
+ private void handleMessage(final Error err)
+ {
+ if (Debug.debug) Debug.print(Debug.ERR, "Handling incoming error: "+err);
+ MethodCall m = null;
+ if (null == pendingCalls) return;
+ synchronized (pendingCalls) {
+ if (pendingCalls.contains(err.getReplySerial()))
+ m = pendingCalls.remove(err.getReplySerial());
+ }
+ if (null != m)
+ m.setReply(err);
+ else
+ synchronized (pendingErrors) {
+ pendingErrors.addLast(err); }
+ }
+ private void handleMessage(final MethodReturn mr)
+ {
+ if (Debug.debug) Debug.print(Debug.ERR, "Handling incoming method return: "+mr);
+ MethodCall m = null;
+ if (null == pendingCalls) return;
+ synchronized (pendingCalls) {
+ if (pendingCalls.contains(mr.getReplySerial()))
+ m = pendingCalls.remove(mr.getReplySerial());
+ }
+ if (null != m) {
+ m.setReply(mr);
+ mr.setCall(m);
+ } else
+ try {
+ if (null != outgoing) synchronized (outgoing) {
+ outgoing.add(new Error(mr, new DBusExecutionException("Spurious reply. No message with the given serial id was awaiting a reply.")));
+ }
+ } catch (DBusException DBe) {}
+ }
+ protected void sendMessage(Message m)
+ {
+ try {
+ if (m instanceof DBusSignal)
+ ((DBusSignal) m).appendbody(this);
+
+ transport.mout.writeMessage(m);
+
+ if (m instanceof MethodCall) {
+ if (0 == (m.getFlags() & Message.Flags.NO_REPLY_EXPECTED))
+ if (null == pendingCalls)
+ ((MethodCall) m).setReply(new Error("org.freedesktop.DBus.Local", "org.freedesktop.DBus.Local.Disconnected", 0, "s", new Object[] { "Disconnected" }));
+ else synchronized (pendingCalls) {
+ pendingCalls.put(m.getSerial(),(MethodCall) m);
+ }
+ }
+ } catch (Exception e) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (m instanceof MethodCall && e instanceof DBusExecutionException)
+ try {
+ ((MethodCall)m).setReply(new Error(m, e));
+ } catch (DBusException DBe) {}
+ else if (m instanceof MethodCall)
+ try {
+ if (Debug.debug) Debug.print(Debug.INFO, "Setting reply to "+m+" as an error");
+ ((MethodCall)m).setReply(new Error(m, new DBusExecutionException("Message Failed to Send: "+e.getMessage())));
+ } catch (DBusException DBe) {}
+ else if (m instanceof MethodReturn)
+ try {
+ transport.mout.writeMessage(new Error(m, e));
+ } catch(IOException IOe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOe);
+ } catch(DBusException IOe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ }
+ }
+ }
+ private Message readIncoming(int timeoutms, EfficientQueue outgoing) throws DBusException
+ {
+ if (null == transport) throw new NotConnected("No transport present");
+ // TODO do something with timeoutms and outgoing
+ Message m = null;
+ try {
+ m = transport.min.readMessage();
+ } catch (IOException IOe) {
+ throw new FatalDBusException(IOe.getMessage());
+ }
+ return m;
+ }
+ /**
+ * Returns the address this connection is connected to.
+ */
+ public BusAddress getAddress() { return new BusAddress(addr); }
+}
diff --git a/org/freedesktop/dbus/ArrayFrob.java b/org/freedesktop/dbus/ArrayFrob.java
index d2eadc9..6b4347e 100644
--- a/org/freedesktop/dbus/ArrayFrob.java
+++ b/org/freedesktop/dbus/ArrayFrob.java
@@ -152,7 +152,7 @@ class ArrayFrob
return type((Object[]) o, c.getComponentType());
} catch (Exception e) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
throw new IllegalArgumentException(e);
}
diff --git a/org/freedesktop/dbus/DBusAsyncReply.java b/org/freedesktop/dbus/DBusAsyncReply.java
index 4fb55d0..d5597e1 100644
--- a/org/freedesktop/dbus/DBusAsyncReply.java
+++ b/org/freedesktop/dbus/DBusAsyncReply.java
@@ -44,8 +44,8 @@ public class DBusAsyncReply<ReturnType>
private DBusExecutionException error = null;
private MethodCall mc;
private Method me;
- private DBusConnection conn;
- DBusAsyncReply(MethodCall mc, Method me, DBusConnection conn)
+ private AbstractConnection conn;
+ DBusAsyncReply(MethodCall mc, Method me, AbstractConnection conn)
{
this.mc = mc;
this.me = me;
@@ -64,7 +64,7 @@ public class DBusAsyncReply<ReturnType>
} catch (DBusExecutionException DBEe) {
error = DBEe;
} catch (DBusException DBe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
error = new DBusExecutionException(DBe.getMessage());
}
}
diff --git a/org/freedesktop/dbus/DBusConnection.java b/org/freedesktop/dbus/DBusConnection.java
index 34ceff8..7f85718 100644
--- a/org/freedesktop/dbus/DBusConnection.java
+++ b/org/freedesktop/dbus/DBusConnection.java
@@ -10,38 +10,19 @@
*/
package org.freedesktop.dbus;
-import java.lang.annotation.Annotation;
-
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
-import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.io.File;
import java.io.IOException;
-import java.util.Arrays;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;
-import java.util.regex.Pattern;
-
import org.freedesktop.DBus;
-import org.freedesktop.dbus.exceptions.NotConnected;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.exceptions.DBusExecutionException;
@@ -56,7 +37,7 @@ import cx.ath.matthew.debug.Debug;
* Signal Handlers and method calls from remote objects are run in their own threads, you MUST handle the concurrency issues.
* </p>
*/
-public class DBusConnection
+public class DBusConnection extends AbstractConnection
{
private class _sighandler implements DBusSigHandler
{
@@ -84,121 +65,7 @@ public class DBusConnection
}
}
}
- private class _thread extends Thread
- {
- public _thread()
- {
- setName("DBusConnection");
- }
- public void run()
- {
- try {
- Message m = null;
- while (_run) {
- m = null;
-
- // read from the wire
- try {
- // this blocks on outgoing being non-empty or a message being available.
- m = readIncoming(TIMEOUT, outgoing);
- if (m != null) {
- if (Debug.debug) Debug.print(Debug.VERBOSE, "Got Incoming Message: "+m);
- synchronized (this) { notifyAll(); }
- if (m instanceof DBusSignal)
- handleMessage((DBusSignal) m);
- else if (m instanceof MethodCall)
- handleMessage((MethodCall) m);
- else if (m instanceof MethodReturn)
- handleMessage((MethodReturn) m);
- else if (m instanceof Error)
- handleMessage((Error) m);
-
- m = null;
- }
- } catch (IOException IOe) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOe);
- try {
- handleMessage(new org.freedesktop.DBus.Local.Disconnected("/"));
- } catch (Exception e) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
- }
- disconnect();
- } catch (Exception e) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
- }
-
- // write to the wire
- if (null != outgoing) synchronized (outgoing) {
- if (!outgoing.isEmpty())
- m = outgoing.remove(); }
- while (null != m) {
- sendMessage(m);
- m = null;
- if (null != outgoing) synchronized (outgoing) {
- if (!outgoing.isEmpty())
- m = outgoing.remove(); }
- }
- }
- if (null != outgoing) synchronized (outgoing) {
- if (!outgoing.isEmpty())
- m = outgoing.remove();
- }
- while (null != m) {
- sendMessage(m);
- m = null;
- if (null != outgoing) synchronized (outgoing) {
- if (!outgoing.isEmpty())
- m = outgoing.remove(); }
- }
- synchronized (this) { notifyAll(); }
- } catch (NotConnected NC) {}
- }
- }
- private class _globalhandler implements org.freedesktop.DBus.Peer, org.freedesktop.DBus.Introspectable
- {
- private String objectpath;
- public _globalhandler()
- {
- this.objectpath = null;
- }
- public _globalhandler(String objectpath)
- {
- this.objectpath = objectpath;
- }
- public boolean isRemote() { return false; }
- public void Ping() { return; }
- public String Introspect()
- {
- String intro = objectTree.Introspect(objectpath);
- if (null == intro)
- throw new DBus.Error.UnknownObject("Introspecting on non-existant object");
- else return
- "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "+
- "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"+intro;
- }
- }
- private class _workerthread extends Thread
- {
- private boolean _run = true;
- public void halt()
- {
- _run = false;
- }
- public void run()
- {
- while (_run) {
- Runnable r = null;
- synchronized (runnables) {
- while (runnables.size() == 0 && _run)
- try { runnables.wait(); } catch (InterruptedException Ie) {}
- if (runnables.size() > 0)
- r = runnables.removeFirst();
- }
- if (null != r) r.run();
- }
- }
- }
/**
* System Bus
*/
@@ -207,66 +74,16 @@ public class DBusConnection
* Session Bus
*/
public static final int SESSION = 1;
- /**
- * Timeout in ms on checking the BUS for incoming messages and sending outgoing messages
- */
- private static final int TIMEOUT = 1;
- /** Initial size of the pending calls map */
- private static final int PENDING_MAP_INITIAL_SIZE = 10;
- static final String BUSNAME_REGEX = "^[-_a-zA-Z][-_a-zA-Z0-9]*(\\.[-_a-zA-Z][-_a-zA-Z0-9]*)*$";
- static final String CONNID_REGEX = "^:[0-9]*\\.[0-9]*$";
- static final String OBJECT_REGEX = "^/([-_a-zA-Z0-9]+(/[-_a-zA-Z0-9]+)*)?$";
- static final byte THREADCOUNT = 4;
- static final int MAX_ARRAY_LENGTH = 67108864;
- static final int MAX_NAME_LENGTH = 255;
public static final String DEFAULT_SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket";
- private Map<String,ExportedObject> exportedObjects;
- private ObjectTree objectTree;
- private Map<DBusInterface,RemoteObject> importedObjects;
- private Map<SignalTuple,Vector<DBusSigHandler>> handledSignals;
- private EfficientMap pendingCalls;
private List<String> busnames;
- private LinkedList<Runnable> runnables;
- private LinkedList<_workerthread> workers;
- private boolean _run;
- private int connid;
- EfficientQueue outgoing;
- LinkedList<Error> pendingErrors;
private static final Map<Object,DBusConnection> conn = new HashMap<Object,DBusConnection>();
- private static final Map<Thread,DBusCallInfo> infomap = new HashMap<Thread,DBusCallInfo>();
private int _refcount = 0;
private Object _reflock = new Object();
private Object connkey;
private DBus _dbus;
- private _thread thread;
- private Transport transport;
- private String addr;
- static final Pattern dollar_pattern = Pattern.compile("[$]");
- public static final boolean EXCEPTION_DEBUG;
- static {
- EXCEPTION_DEBUG = (null != System.getenv("DBUS_JAVA_EXCEPTION_DEBUG"));
- if (EXCEPTION_DEBUG) {
- Debug.print("Debugging of internal exceptions enabled");
- Debug.setThrowableTraces(true);
- }
- if (Debug.debug) {
- File f = new File("debug.conf");
- if (f.exists()) {
- Debug.print("Loading debug config file: "+f);
- try {
- Debug.loadConfig(f);
- } catch (IOException IOe) {}
- } else {
- Properties p = new Properties();
- p.setProperty("ALL", "INFO");
- Debug.print("debug config file "+f+" does not exist, not loading.");
- }
- Debug.setHexDump(true);
- }
- }
/**
* Connect to the BUS. If a connection already exists to the specified Bus, a reference to it is returned.
@@ -326,29 +143,12 @@ public class DBusConnection
@SuppressWarnings("unchecked")
private DBusConnection(String address) throws DBusException
{
- exportedObjects = new HashMap<String,ExportedObject>();
- importedObjects = new HashMap<DBusInterface,RemoteObject>();
- exportedObjects.put(null, new ExportedObject(new _globalhandler()));
- handledSignals = new HashMap<SignalTuple,Vector<DBusSigHandler>>();
- pendingCalls = new EfficientMap(PENDING_MAP_INITIAL_SIZE);
+ super(address);
busnames = new Vector<String>();
- outgoing = new EfficientQueue(PENDING_MAP_INITIAL_SIZE);
- pendingErrors = new LinkedList<Error>();
- runnables = new LinkedList<Runnable>();
- workers = new LinkedList<_workerthread>();
- objectTree = new ObjectTree();
- synchronized (workers) {
- for (int i = 0; i < THREADCOUNT; i++) {
- _workerthread t = new _workerthread();
- t.start();
- workers.add(t);
- }
- }
- _run = true;
+
synchronized (_reflock) {
_refcount = 1;
}
- addr = address;
try {
transport = new Transport(addr);
@@ -357,10 +157,9 @@ public class DBusConnection
throw new DBusException("Failed to connect to bus "+IOe.getMessage());
}
- // start listening
- thread = new _thread();
- thread.start();
-
+ // start listening for calls
+ listen();
+
// register disconnect handlers
DBusSigHandler h = new _sighandler();
addSigHandlerWithoutMatch(org.freedesktop.DBus.Local.Disconnected.class, h);
@@ -376,50 +175,6 @@ public class DBusConnection
}
}
- /**
- * Change the number of worker threads to receive method calls and handle signals.
- * Default is 4 threads
- * @param newcount The new number of worker Threads to use.
- */
- public void changeThreadCount(byte newcount)
- {
- synchronized (workers) {
- if (workers.size() > newcount) {
- int n = workers.size() - newcount;
- for (int i = 0; i < n; i++) {
- _workerthread t = workers.removeFirst();
- t.halt();
- }
- } else if (workers.size() < newcount) {
- int n = newcount-workers.size();
- for (int i = 0; i < n; i++) {
- _workerthread t = new _workerthread();
- t.start();
- workers.add(t);
- }
- }
- }
- }
- private void addRunnable(Runnable r)
- {
- synchronized(runnables) {
- runnables.add(r);
- runnables.notifyAll();
- }
- }
-
- String getExportedObject(DBusInterface i) throws DBusException
- {
- for (String s: exportedObjects.keySet())
- if (exportedObjects.get(s).object.equals(i))
- return s;
-
- String s = importedObjects.get(i).objectpath;
- if (null != s) return s;
-
- throw new DBusException("Not an object exported or imported by this connection");
- }
-
DBusInterface dynamicProxy(String source, String path) throws DBusException
{
try {
@@ -470,19 +225,6 @@ public class DBusConnection
return dynamicProxy(source, path);
}
- /**
- * Returns a structure with information on the current method call.
- * @return the DBusCallInfo for this method call, or null if we are not in a method call.
- */
- public static DBusCallInfo getCallInfo()
- {
- DBusCallInfo info;
- synchronized (infomap) {
- info = infomap.get(Thread.currentThread());
- }
- return info;
- }
-
/**
* Request a bus name.
* Request the well known name that this should respond to on the Bus.
@@ -530,53 +272,6 @@ public class DBusConnection
names.addAll(busnames);
return names.toArray(new String[0]);
}
- /**
- * 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",
- * 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.
- * @throws DBusException If the objectpath is already exporting an object.
- * or if objectpath is incorrectly formatted,
- */
- public void exportObject(String objectpath, DBusInterface object) throws DBusException
- {
- if (!objectpath.matches(OBJECT_REGEX)||objectpath.length() > MAX_NAME_LENGTH)
- throw new DBusException("Invalid object path ("+objectpath+")");
- if (null == objectpath || "".equals(objectpath))
- throw new DBusException("Must Specify an Object Path");
- synchronized (exportedObjects) {
- if (null != exportedObjects.get(objectpath))
- throw new DBusException("Object already exported");
- ExportedObject eo = new ExportedObject(object);
- exportedObjects.put(objectpath, eo);
- objectTree.add(objectpath, object, eo.introspectiondata);
- }
- }
- /**
- * Stop Exporting an object
- * @param objectpath The objectpath to stop exporting.
- */
- public void unExportObject(String objectpath)
- {
- synchronized (exportedObjects) {
- exportedObjects.remove(objectpath);
- }
- }
- /**
- * Return a reference to a remote object.
- * This method will resolve the well known name (if given) to a unique bus name when you call it.
- * This means that if a well known name is released by one process and acquired by another calls to
- * objects gained from this method will continue to operate on the original process.
- * @param busname The bus name to connect to. Usually a well known bus name in dot-notation (such as "org.freedesktop.local")
- * or may be a DBus address such as ":1-16".
- * @param objectpath The path on which the process is exporting the object.$
- * @param type The interface they are exporting it on. This type must have the same full class name and exposed method signatures
- * as the interface the remote object is exporting.
- * @return A reference to a remote object.
- * @throws ClassCastException If type is not a sub-type of DBusInterface
- * @throws DBusException If busname or objectpath are incorrectly formatted or type is not in a package.
- */
public DBusInterface getPeerRemoteObject(String busname, String objectpath, Class<? extends DBusInterface> type) throws DBusException
{
return getPeerRemoteObject(busname, objectpath, type, true);
@@ -742,44 +437,6 @@ public class DBusConnection
return i;
}
/**
- * Send a signal.
- * @param signal The signal to send.
- */
- public void sendSignal(DBusSignal signal)
- {
- if (null == outgoing) return;
- synchronized (outgoing) {
- outgoing.add(signal); }
- }
- /**
- * Remove a Signal Handler.
- * Stops listening for this signal.
- * @param type The signal to watch for.
- * @throws DBusException If listening for the signal on the bus failed.
- * @throws ClassCastException If type is not a sub-type of DBusSignal.
- */
- public <T extends DBusSignal> void removeSigHandler(Class<T> type, DBusSigHandler<T> handler) throws DBusException
- {
- if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException("Not A DBus Signal");
- removeSigHandler(new DBusMatchRule(type), handler);
- }
- /**
- * Remove a Signal Handler.
- * Stops listening for this signal.
- * @param type The signal to watch for.
- * @param object The object emitting the signal.
- * @throws DBusException If listening for the signal on the bus failed.
- * @throws ClassCastException If type is not a sub-type of DBusSignal.
- */
- public <T extends DBusSignal> void removeSigHandler(Class<T> type, DBusInterface object, DBusSigHandler<T> handler) throws DBusException
- {
- if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException("Not A DBus Signal");
- String objectpath = importedObjects.get(object).objectpath;
- if (!objectpath.matches(OBJECT_REGEX)||objectpath.length() > MAX_NAME_LENGTH)
- throw new DBusException("Invalid object path ("+objectpath+")");
- removeSigHandler(new DBusMatchRule(type, null, objectpath), handler);
- }
- /**
* Remove a Signal Handler.
* Stops listening for this signal.
* @param type The signal to watch for.
@@ -815,7 +472,7 @@ public class DBusConnection
throw new DBusException("Invalid object path ("+objectpath+")");
removeSigHandler(new DBusMatchRule(type, source, objectpath), handler);
}
- private <T extends DBusSignal> void removeSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException
+ protected <T extends DBusSignal> void removeSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException
{
SignalTuple key = new SignalTuple(rule.getInterface(), rule.getMember(), rule.getObject(), rule.getSource());
@@ -837,36 +494,6 @@ public class DBusConnection
}
/**
* Add a Signal Handler.
- * Adds a signal handler to call when a signal is received which matches the specified type and name.
- * @param type The signal to watch for.
- * @param handler The handler to call when a signal is received.
- * @throws DBusException If listening for the signal on the bus failed.
- * @throws ClassCastException If type is not a sub-type of DBusSignal.
- */
- public <T extends DBusSignal> void addSigHandler(Class<T> type, DBusSigHandler<T> handler) throws DBusException
- {
- if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException("Not A DBus Signal");
- addSigHandler(new DBusMatchRule(type), handler);
- }
- /**
- * Add a Signal Handler.
- * Adds a signal handler to call when a signal is received which matches the specified type, name and object.
- * @param type The signal to watch for.
- * @param object The object from which the signal will be emitted
- * @param handler The handler to call when a signal is received.
- * @throws DBusException If listening for the signal on the bus failed.
- * @throws ClassCastException If type is not a sub-type of DBusSignal.
- */
- public <T extends DBusSignal> void addSigHandler(Class<T> type, DBusInterface object, DBusSigHandler<T> handler) throws DBusException
- {
- if (!DBusSignal.class.isAssignableFrom(type)) throw new ClassCastException("Not A DBus Signal");
- String objectpath = importedObjects.get(object).objectpath;
- if (!objectpath.matches(OBJECT_REGEX)||objectpath.length() > MAX_NAME_LENGTH)
- throw new DBusException("Invalid object path ("+objectpath+")");
- addSigHandler(new DBusMatchRule(type, null, objectpath), handler);
- }
- /**
- * Add a Signal Handler.
* Adds a signal handler to call when a signal is received which matches the specified type, name and source.
* @param type The signal to watch for.
* @param source The process which will send the signal. This <b>MUST</b> be a unique bus name and not a well known name.
@@ -903,7 +530,7 @@ public class DBusConnection
throw new DBusException("Invalid object path ("+objectpath+")");
addSigHandler(new DBusMatchRule(type, source, objectpath), handler);
}
- private <T extends DBusSignal> void addSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException
+ protected <T extends DBusSignal> void addSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException
{
try {
_dbus.AddMatch(rule.toString());
@@ -922,20 +549,6 @@ public class DBusConnection
v.add(handler);
}
}
- private void addSigHandlerWithoutMatch(Class signal, DBusSigHandler handler) throws DBusException
- {
- DBusMatchRule rule = new DBusMatchRule(signal);
- SignalTuple key = new SignalTuple(rule.getInterface(), rule.getMember(), rule.getObject(), rule.getSource());
- synchronized (handledSignals) {
- Vector<DBusSigHandler> v = handledSignals.get(key);
- if (null == v) {
- v = new Vector<DBusSigHandler>();
- v.add(handler);
- handledSignals.put(key, v);
- } else
- v.add(handler);
- }
- }
/**
* Disconnect from the Bus.
* This only disconnects when the last reference to the bus has disconnect called on it
@@ -972,319 +585,10 @@ public class DBusConnection
}
} catch (DBusException DBe) {}
- // run all pending tasks.
- while (runnables.size() > 0)
- synchronized (runnables) {
- runnables.notifyAll();
- }
-
- // stop the main thread
- _run = false;
- try {
- synchronized (thread) { thread.wait(); }
- } catch (InterruptedException Ie) {}
-
- // disconnect from the trasport layer
- try {
- transport.disconnect();
- } catch (IOException IOe) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOe);
- }
conn.remove(addr);
-
- // stop all the workers
- synchronized(workers) {
- for (_workerthread t: workers)
- t.halt();
- }
-
- // make sure none are blocking on the runnables queue still
- synchronized (runnables) {
- runnables.notifyAll();
- }
+ super.disconnect();
}
}
}
}
- public void finalize()
- {
- disconnect();
- }
- /**
- * Return any DBus error which has been received.
- * @return A DBusExecutionException, or null if no error is pending.
- */
- public DBusExecutionException getError()
- {
- synchronized (pendingErrors) {
- if (pendingErrors.size() == 0) return null;
- else
- return pendingErrors.removeFirst().getException();
- }
- }
-
- /**
- * Call a method asynchronously and get a handle with which to get the reply.
- * @param object The remote object on which to call the method.
- * @param m The name of the method on the interface to call.
- * @param parameters The parameters to call the method with.
- * @return A handle to the call.
- */
- public DBusAsyncReply callMethodAsync(DBusInterface object, String m, Object... parameters)
- {
- Class[] types = new Class[parameters.length];
- for (int i = 0; i < parameters.length; i++)
- types[i] = parameters[i].getClass();
- RemoteObject ro = importedObjects.get(object);
-
- try {
- Method me;
- if (null == ro.iface)
- me = object.getClass().getMethod(m, types);
- else
- me = ro.iface.getMethod(m, types);
- return (DBusAsyncReply) RemoteInvocationHandler.executeRemoteMethod(ro, me, this, true, parameters);
- } catch (DBusExecutionException DBEe) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
- throw DBEe;
- } catch (Exception e) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
- throw new DBusExecutionException(e.getMessage());
- }
- }
-
- private void handleMessage(final MethodCall m) throws DBusException
- {
- if (Debug.debug) Debug.print(Debug.ERR, "Handling incoming method call: "+m);
- // get the method signature
- Object[] params = m.getParameters();
-
- ExportedObject eo = null;
- Method meth = null;
- Object o;
-
- synchronized (exportedObjects) {
- eo = exportedObjects.get(null);
- }
- if (null != eo) {
- meth = eo.methods.get(new MethodTuple(m.getName(), m.getSig()));
- }
- if (null != meth)
- o = new _globalhandler(m.getPath());
-
- else {
- // now check for specific exported functions
-
- synchronized (exportedObjects) {
- eo = exportedObjects.get(m.getPath());
- }
-
- if (null == eo) {
- try {
- if (null != outgoing) synchronized (outgoing) {
- outgoing.add(new Error(m, new DBus.Error.UnknownObject(m.getPath()+" is not an object provided by this process."))); }
- } catch (DBusException DBe) {}
- return;
- }
- meth = eo.methods.get(new MethodTuple(m.getName(), m.getSig()));
- if (null == meth) {
- try {
- if (null != outgoing) synchronized (outgoing) {
- outgoing.add(new Error(m, new DBus.Error.UnknownMethod("The method `"+m.getInterface()+"."+m.getName()+"' does not exist on this object."))); }
- } catch (DBusException DBe) {}
- return;
- }
- o = eo.object;
- }
-
- // now execute it
- final Method me = meth;
- final Object ob = o;
- final EfficientQueue outqueue = outgoing;
- final boolean noreply = (1 == (m.getFlags() & Message.Flags.NO_REPLY_EXPECTED));
- final DBusCallInfo info = new DBusCallInfo(m);
- final DBusConnection conn = this;
- addRunnable(new Runnable()
- {
- public void run()
- {
- try {
- Type[] ts = me.getGenericParameterTypes();
- m.setArgs(Marshalling.deSerializeParameters(m.getParameters(), ts, conn));
- if (Debug.debug) Debug.print(Debug.DEBUG, "Deserialised "+Arrays.deepToString(m.getParameters())+" to types "+Arrays.deepToString(ts));
- } catch (Exception e) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
- try {
- synchronized (outqueue) {
- outqueue.add(new Error(m, new DBus.Error.UnknownMethod("Failure in de-serializing message ("+e+")")));
- }
- } catch (DBusException DBe) {}
- return;
- }
-
- try {
- synchronized (infomap) {
- infomap.put(Thread.currentThread(), info);
- }
- Object result;
- try {
- result = me.invoke(ob, m.getParameters());
- } catch (InvocationTargetException ITe) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, ITe.getCause());
- throw ITe.getCause();
- }
- synchronized (infomap) {
- infomap.remove(Thread.currentThread());
- }
- if (!noreply) {
- MethodReturn reply;
- if (Void.TYPE.equals(me.getReturnType()))
- reply = new MethodReturn(m, null);
- else {
- StringBuffer sb = new StringBuffer();
- for (String s: Marshalling.getDBusType(me. getGenericReturnType()))
- sb.append(s);
- Object[] nr = Marshalling.convertParameters(new Object[] { result }, new Type[] {me.getGenericReturnType()}, conn);
-
- reply = new MethodReturn(m, sb.toString(),nr);
- }
- synchronized (outqueue) {
- outqueue.add(reply);
- }
- }
- } catch (DBusExecutionException DBEe) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
- try {
- synchronized (outqueue) {
- outqueue.add(new Error(m, DBEe));
- }
- } catch (DBusException DBe) {}
- } catch (Throwable e) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
- try {
- synchronized (outqueue) {
- outqueue.add(new Error(m, new DBusExecutionException("Error Executing Method "+m.getInterface()+"."+m.getName()+": "+e.getMessage())));
- }
- } catch (DBusException DBe) {}
- }
- }
- });
- }
- @SuppressWarnings({"unchecked","deprecation"})
- private void handleMessage(final DBusSignal s)
- {
- if (Debug.debug) Debug.print(Debug.ERR, "Handling incoming signal: "+s);
- Vector<DBusSigHandler> v = new Vector<DBusSigHandler>();
- synchronized(handledSignals) {
- Vector<DBusSigHandler> t;
- t = handledSignals.get(new SignalTuple(s.getInterface(), s.getName(), null, null));
- if (null != t) v.addAll(t);
- t = handledSignals.get(new SignalTuple(s.getInterface(), s.getName(), s.getPath(), null));
- if (null != t) v.addAll(t);
- t = handledSignals.get(new SignalTuple(s.getInterface(), s.getName(), null, s.getSource()));
- if (null != t) v.addAll(t);
- t = handledSignals.get(new SignalTuple(s.getInterface(), s.getName(), s.getPath(), s.getSource()));
- if (null != t) v.addAll(t);
- }
- if (0 == v.size()) return;
- final EfficientQueue outqueue = outgoing;
- final DBusConnection conn = this;
- for (final DBusSigHandler h: v)
- addRunnable(new Runnable() { public void run() {
- {
- try {
- DBusSignal rs;
- if (s instanceof DBusSignal.internalsig || s.getClass().equals(DBusSignal.class))
- rs = s.createReal(conn);
- else
- rs = s;
- h.handle(rs);
- } catch (DBusException DBe) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
- try {
- synchronized (outqueue) {
- outqueue.add(new Error(s, new DBusExecutionException("Error handling signal "+s.getInterface()+"."+s.getName()+": "+DBe.getMessage())));
- }
- } catch (DBusException DBe2) {}
- }
- }
- } });
- }
- private void handleMessage(final Error err)
- {
- if (Debug.debug) Debug.print(Debug.ERR, "Handling incoming error: "+err);
- MethodCall m = null;
- if (null == pendingCalls) return;
- synchronized (pendingCalls) {
- if (pendingCalls.contains(err.getReplySerial()))
- m = pendingCalls.remove(err.getReplySerial());
- }
- if (null != m)
- m.setReply(err);
- else
- synchronized (pendingErrors) {
- pendingErrors.addLast(err); }
- }
- private void handleMessage(final MethodReturn mr)
- {
- if (Debug.debug) Debug.print(Debug.ERR, "Handling incoming method return: "+mr);
- MethodCall m = null;
- if (null == pendingCalls) return;
- synchronized (pendingCalls) {
- if (pendingCalls.contains(mr.getReplySerial()))
- m = pendingCalls.remove(mr.getReplySerial());
- }
- if (null != m) {
- m.setReply(mr);
- mr.setCall(m);
- } else
- try {
- if (null != outgoing) synchronized (outgoing) {
- outgoing.add(new Error(mr, new DBusExecutionException("Spurious reply. No message with the given serial id was awaiting a reply.")));
- }
- } catch (DBusException DBe) {}
- }
- private void sendMessage(Message m)
- {
- try {
- if (m instanceof DBusSignal)
- ((DBusSignal) m).appendbody(this);
-
- transport.mout.writeMessage(m);
-
- if (m instanceof MethodCall) {
- if (0 == (m.getFlags() & Message.Flags.NO_REPLY_EXPECTED))
- if (null == pendingCalls)
- ((MethodCall) m).setReply(new Error("org.freedesktop.DBus.Local", "org.freedesktop.DBus.Local.Disconnected", 0, "s", new Object[] { "Disconnected" }));
- else synchronized (pendingCalls) {
- pendingCalls.put(m.getSerial(),(MethodCall) m);
- }
- }
- } catch (Exception e) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
- if (m instanceof MethodCall && e instanceof DBusExecutionException)
- try {
- ((MethodCall)m).setReply(new Error(m, e));
- } catch (DBusException DBe) {}
- else if (m instanceof MethodCall)
- try {
- if (Debug.debug) Debug.print(Debug.INFO, "Setting reply to "+m+" as an error");
- ((MethodCall)m).setReply(new Error(m, new DBusExecutionException("Message Failed to Send: "+e.getMessage())));
- } catch (DBusException DBe) {}
- else if (m instanceof MethodReturn)
- try {
- transport.mout.writeMessage(new Error(m, e));
- } catch(IOException IOe) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOe);
- } catch(DBusException IOe) {
- if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
- }
- }
- }
- private Message readIncoming(int timeoutms, EfficientQueue outgoing) throws IOException, DBusException
- {
- // TODO do something with timeoutms and outgoing
- Message m = transport.min.readMessage();
- return m;
- }
}
diff --git a/org/freedesktop/dbus/DBusMatchRule.java b/org/freedesktop/dbus/DBusMatchRule.java
index bc36a72..b231e1f 100644
--- a/org/freedesktop/dbus/DBusMatchRule.java
+++ b/org/freedesktop/dbus/DBusMatchRule.java
@@ -63,14 +63,14 @@ public class DBusMatchRule
public DBusMatchRule(Class c) throws DBusException
{
if (DBusInterface.class.isAssignableFrom(c)) {
- iface = DBusConnection.dollar_pattern.matcher(c.getName()).replaceAll(".");
+ iface = AbstractConnection.dollar_pattern.matcher(c.getName()).replaceAll(".");
if (!iface.matches(".*\\..*"))
throw new DBusException("DBusInterfaces must be defined in a package.");
member = null;
type = null;
}
else if (DBusSignal.class.isAssignableFrom(c)) {
- iface = DBusConnection.dollar_pattern.matcher(c.getEnclosingClass().getName()).replaceAll(".");
+ iface = AbstractConnection.dollar_pattern.matcher(c.getEnclosingClass().getName()).replaceAll(".");
// Don't export things which are invalid D-Bus interfaces
if (!iface.matches(".*\\..*"))
throw new DBusException("DBusInterfaces must be defined in a package.");
@@ -78,14 +78,14 @@ public class DBusMatchRule
type = "signal";
}
else if (Error.class.isAssignableFrom(c)) {
- iface = DBusConnection.dollar_pattern.matcher(c.getName()).replaceAll(".");
+ iface = AbstractConnection.dollar_pattern.matcher(c.getName()).replaceAll(".");
if (!iface.matches(".*\\..*"))
throw new DBusException("DBusInterfaces must be defined in a package.");
member = null;
type = "error";
}
else if (DBusExecutionException.class.isAssignableFrom(c)) {
- iface = DBusConnection.dollar_pattern.matcher(c.getClass().getName()).replaceAll(".");
+ iface = AbstractConnection.dollar_pattern.matcher(c.getClass().getName()).replaceAll(".");
if (!iface.matches(".*\\..*"))
throw new DBusException("DBusInterfaces must be defined in a package.");
member = null;
diff --git a/org/freedesktop/dbus/DBusSignal.java b/org/freedesktop/dbus/DBusSignal.java
index 67afd3d..8bb8290 100644
--- a/org/freedesktop/dbus/DBusSignal.java
+++ b/org/freedesktop/dbus/DBusSignal.java
@@ -74,7 +74,7 @@ public class DBusSignal extends Message
{
String type = "";
if (null != c.getEnclosingClass())
- type = DBusConnection.dollar_pattern.matcher(c.getEnclosingClass().getName()).replaceAll(".");
+ type = AbstractConnection.dollar_pattern.matcher(c.getEnclosingClass().getName()).replaceAll(".");
DBusSignal s = new internalsig(source, objectpath, type, c.getSimpleName(), sig, parameters, serial);
s.c = c;
return s;
@@ -91,7 +91,7 @@ public class DBusSignal extends Message
} while (null == c && name.matches(".*\\..*"));
return c;
}
- DBusSignal createReal(DBusConnection conn) throws DBusException
+ DBusSignal createReal(AbstractConnection conn) throws DBusException
{
if (null == c)
c = createSignalClass(getInterface()+"$"+getName());
@@ -129,7 +129,7 @@ public class DBusSignal extends Message
s.bytecounter = wiredata.length;
return s;
} catch (Exception e) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
throw new DBusException(e.getMessage());
}
}
@@ -144,7 +144,7 @@ public class DBusSignal extends Message
{
super(Message.Endian.BIG, Message.MessageType.SIGNAL, (byte) 0);
- if (!objectpath.matches(DBusConnection.OBJECT_REGEX)) throw new DBusException("Invalid object path ("+objectpath+")");
+ if (!objectpath.matches(AbstractConnection.OBJECT_REGEX)) throw new DBusException("Invalid object path ("+objectpath+")");
Class tc = getClass();
String member = tc.getSimpleName();
@@ -155,7 +155,7 @@ public class DBusSignal extends Message
enc.getName().equals(enc.getSimpleName()))
throw new DBusException("Signals must be declared as a member of a class implementing DBusInterface which is the member of a package.");
else
- iface = DBusConnection.dollar_pattern.matcher(enc.getName()).replaceAll(".");
+ iface = AbstractConnection.dollar_pattern.matcher(enc.getName()).replaceAll(".");
headers.put(Message.HeaderField.PATH,objectpath);
headers.put(Message.HeaderField.MEMBER,member);
@@ -187,7 +187,7 @@ public class DBusSignal extends Message
headers.put(Message.HeaderField.SIGNATURE,sig);
setArgs(args);
} catch (Exception e) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
throw new DBusException("Failed to add signal parameters: "+e.getMessage());
}
}
@@ -197,7 +197,7 @@ public class DBusSignal extends Message
append("ua(yv)", ++serial, hargs.toArray());
pad((byte)8);
}
- void appendbody(DBusConnection conn) throws DBusException
+ void appendbody(AbstractConnection conn) throws DBusException
{
if (bodydone) return;
diff --git a/org/freedesktop/dbus/DirectConnection.java b/org/freedesktop/dbus/DirectConnection.java
new file mode 100644
index 0000000..dedc018
--- /dev/null
+++ b/org/freedesktop/dbus/DirectConnection.java
@@ -0,0 +1,210 @@
+/*
+ D-Bus Java Implementation
+ Copyright (c) 2005-2006 Matthew Johnson
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of either the GNU General Public License Version 2 or the
+ Academic Free Licence Version 2.1.
+
+ Full licence texts are included in the COPYING file with this program.
+*/
+package org.freedesktop.dbus;
+
+import java.lang.reflect.Proxy;
+import java.io.File;
+import java.io.IOException;
+import java.util.Random;
+import java.util.Vector;
+
+import org.freedesktop.DBus;
+import org.freedesktop.dbus.exceptions.DBusException;
+
+import cx.ath.matthew.debug.Debug;
+
+/** Handles a peer to peer connection between two applications withou a bus daemon.
+ * <p>
+ * Signal Handlers and method calls from remote objects are run in their own threads, you MUST handle the concurrency issues.
+ * </p>
+ */
+public class DirectConnection extends AbstractConnection
+{
+ /**
+ * Create a direct connection to another application.
+ * @param address The address to connect to. This is a standard D-Bus address, except that the additional parameter 'listen=true' should be added in the application which is creating the socket.
+ */
+ public DirectConnection(String address) throws DBusException
+ {
+ super(address);
+
+ try {
+ transport = new Transport(addr);
+ } catch (IOException IOe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOe);
+ throw new DBusException("Failed to connect to bus "+IOe.getMessage());
+ }
+
+ listen();
+ }
+
+ /**
+ * Creates a bus address for a randomly generated abstract unix socket.
+ * @return a random bus address.
+ */
+ public static String createDynamicSession()
+ {
+ String address = "unix:listen=true";
+ String path = "/tmp/dbus-XXXXXXXXXX";
+ Random r = new Random();
+ do {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < 10; i++)
+ sb.append((char) ((Math.abs(r.nextInt()) % 26) + 65));
+ path = path.replaceAll("..........$", sb.toString());
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Trying path "+path);
+ } while ((new File(path)).exists());
+ address += ",abstract="+path;
+ address += ",guid="+Transport.genGUID();
+ if (Debug.debug) Debug.print("Created Session address: "+address);
+ return address;
+ }
+ DBusInterface dynamicProxy(String path) throws DBusException
+ {
+ try {
+ DBus.Introspectable intro = (DBus.Introspectable) getRemoteObject(path, DBus.Introspectable.class);
+ String data = intro.Introspect();
+ String[] tags = data.split("[<>]");
+ Vector<String> ifaces = new Vector<String>();
+ for (String tag: tags) {
+ if (tag.startsWith("interface")) {
+ ifaces.add(tag.replaceAll("^interface *name *= *['\"]([^'\"]*)['\"].*$", "$1"));
+ }
+ }
+ Vector<Class> ifcs = new Vector<Class>();
+ for(String iface: ifaces) {
+ int j = 0;
+ while (j >= 0) {
+ try {
+ ifcs.add(Class.forName(iface));
+ break;
+ } catch (Exception e) {}
+ j = iface.lastIndexOf(".");
+ char[] cs = iface.toCharArray();
+ if (j >= 0) {
+ cs[j] = '$';
+ iface = String.valueOf(cs);
+ }
+ }
+ }
+
+ if (ifcs.size() == 0) throw new DBusException("Could not find an interface to cast to");
+
+ RemoteObject ro = new RemoteObject(null, path, null, false);
+ DBusInterface newi = (DBusInterface) Proxy.newProxyInstance(ifcs.get(0).getClassLoader(),
+ (Class[]) ifcs.toArray(new Class[0]), new RemoteInvocationHandler(this, ro));
+ importedObjects.put(newi, ro);
+ return newi;
+ } catch (Exception e) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ throw new DBusException("Failed to create proxy object for "+path+". Reason: "+e.getMessage());
+ }
+ }
+
+ DBusInterface getExportedObject(String path) throws DBusException
+ {
+ ExportedObject o = exportedObjects.get(path);
+ if (null != o) return o.object;
+ return dynamicProxy(path);
+ }
+
+ /**
+ * Return a reference to a remote object.
+ * This method will always refer to the well known name (if given) rather than resolving it to a unique bus name.
+ * In particular this means that if a process providing the well known name disappears and is taken over by another process
+ * proxy objects gained by this method will make calls on the new proccess.
+ *
+ * This method will use bus introspection to determine the interfaces on a remote object and so
+ * <b>may block</b> and <b>may fail</b>. The resulting proxy object will, however, be castable
+ * to any interface it implements. It will also autostart the process if applicable. Also note
+ * that the resulting proxy may fail to execute the correct method with overloaded methods
+ * and that complex types may fail in interesting ways. Basically, if something odd happens,
+ * try specifying the interface explicitly.
+ *
+ * @param objectpath The path on which the process is exporting the object.
+ * @return A reference to a remote object.
+ * @throws ClassCastException If type is not a sub-type of DBusInterface
+ * @throws DBusException If busname or objectpath are incorrectly formatted.
+ */
+ public DBusInterface getRemoteObject(String objectpath) throws DBusException
+ {
+ if (null == objectpath) throw new DBusException("Invalid object path (null)");
+
+ if (!objectpath.matches(OBJECT_REGEX) || objectpath.length() > MAX_NAME_LENGTH)
+ throw new DBusException("Invalid object path ("+objectpath+")");
+
+ return dynamicProxy(objectpath);
+ }
+
+ /**
+ * Return a reference to a remote object.
+ * This method will always refer to the well known name (if given) rather than resolving it to a unique bus name.
+ * In particular this means that if a process providing the well known name disappears and is taken over by another process
+ * proxy objects gained by this method will make calls on the new proccess.
+ * @param objectpath The path on which the process is exporting the object.
+ * @param type The interface they are exporting it on. This type must have the same full class name and exposed method signatures
+ * as the interface the remote object is exporting.
+ * @return A reference to a remote object.
+ * @throws ClassCastException If type is not a sub-type of DBusInterface
+ * @throws DBusException If busname or objectpath are incorrectly formatted or type is not in a package.
+ */
+ public DBusInterface getRemoteObject(String objectpath, Class<? extends DBusInterface> type) throws DBusException
+ {
+ if (null == objectpath) throw new DBusException("Invalid object path (null)");
+ if (null == type) throw new ClassCastException("Not A DBus Interface");
+
+ if (!objectpath.matches(OBJECT_REGEX) || objectpath.length() > MAX_NAME_LENGTH)
+ throw new DBusException("Invalid object path ("+objectpath+")");
+
+ if (!DBusInterface.class.isAssignableFrom(type)) throw new ClassCastException("Not A DBus Interface");
+
+ // don't let people import things which don't have a
+ // valid D-Bus interface name
+ if (type.getName().equals(type.getSimpleName()))
+ throw new DBusException("DBusInterfaces cannot be declared outside a package");
+
+ RemoteObject ro = new RemoteObject(null, objectpath, type, false);
+ DBusInterface i = (DBusInterface) Proxy.newProxyInstance(type.getClassLoader(),
+ new Class[] { type }, new RemoteInvocationHandler(this, ro));
+ importedObjects.put(i, ro);
+ return i;
+ }
+ protected <T extends DBusSignal> void removeSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException
+ {
+ SignalTuple key = new SignalTuple(rule.getInterface(), rule.getMember(), rule.getObject(), rule.getSource());
+ synchronized (handledSignals) {
+ Vector<DBusSigHandler> v = handledSignals.get(key);
+ if (null != v) {
+ v.remove(handler);
+ if (0 == v.size()) {
+ handledSignals.remove(key);
+ }
+ }
+ }
+ }
+ protected <T extends DBusSignal> void addSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException
+ {
+ SignalTuple key = new SignalTuple(rule.getInterface(), rule.getMember(), rule.getObject(), rule.getSource());
+ synchronized (handledSignals) {
+ Vector<DBusSigHandler> v = handledSignals.get(key);
+ if (null == v) {
+ v = new Vector<DBusSigHandler>();
+ v.add(handler);
+ handledSignals.put(key, v);
+ } else
+ v.add(handler);
+ }
+ }
+ DBusInterface getExportedObject(String source, String path) throws DBusException
+ {
+ return getExportedObject(path);
+ }
+}
diff --git a/org/freedesktop/dbus/EfficientQueue.java b/org/freedesktop/dbus/EfficientQueue.java
index ab2a4e4..533fe5a 100644
--- a/org/freedesktop/dbus/EfficientQueue.java
+++ b/org/freedesktop/dbus/EfficientQueue.java
@@ -93,4 +93,11 @@ class EfficientQueue
// check if find succeeds
return start == end;
}
+ public int size()
+ {
+ if (end >= start)
+ return end-start;
+ else
+ return mv.length-start+end;
+ }
}
diff --git a/org/freedesktop/dbus/Error.java b/org/freedesktop/dbus/Error.java
index ac69697..f77d6c6 100644
--- a/org/freedesktop/dbus/Error.java
+++ b/org/freedesktop/dbus/Error.java
@@ -28,16 +28,20 @@ public class Error extends Message
{
super(Message.Endian.BIG, Message.MessageType.ERROR, (byte) 0);
- if (null == dest || null == errorName)
- throw new MessageFormatException("Must specify destination and error name to Errors.");
+ if (null == errorName)
+ throw new MessageFormatException("Must specify error name to Errors.");
headers.put(Message.HeaderField.REPLY_SERIAL,replyserial);
headers.put(Message.HeaderField.ERROR_NAME,errorName);
- headers.put(Message.HeaderField.DESTINATION,dest);
Vector<Object> hargs = new Vector<Object>();
hargs.add(new Object[] { Message.HeaderField.ERROR_NAME, new Object[] { ArgumentType.STRING_STRING, errorName } });
- hargs.add(new Object[] { Message.HeaderField.DESTINATION, new Object[] { ArgumentType.STRING_STRING, dest } });
hargs.add(new Object[] { Message.HeaderField.REPLY_SERIAL, new Object[] { ArgumentType.UINT32_STRING, replyserial } });
+
+ if (null != dest) {
+ headers.put(Message.HeaderField.DESTINATION,dest);
+ hargs.add(new Object[] { Message.HeaderField.DESTINATION, new Object[] { ArgumentType.STRING_STRING, dest } });
+ }
+
if (null != sig) {
hargs.add(new Object[] { Message.HeaderField.SIGNATURE, new Object[] { ArgumentType.SIGNATURE_STRING, sig } });
headers.put(Message.HeaderField.SIGNATURE,sig);
@@ -55,7 +59,7 @@ public class Error extends Message
}
public Error(Message m, Exception e) throws DBusException
{
- this(m.getSource(), DBusConnection.dollar_pattern.matcher(e.getClass().getName()).replaceAll("."), m.getSerial(), "s", e.getMessage());
+ this(m.getSource(), AbstractConnection.dollar_pattern.matcher(e.getClass().getName()).replaceAll("."), m.getSerial(), "s", e.getMessage());
}
@SuppressWarnings("unchecked")
private static Class<? extends DBusExecutionException> createExceptionClass(String name)
@@ -91,8 +95,8 @@ public class Error extends Message
ex.setType(getName());
return ex;
} catch (Exception e) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug && null != e.getCause())
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug && null != e.getCause())
Debug.print(Debug.ERR, e.getCause());
DBusExecutionException ex;
Object[] args = null;
diff --git a/org/freedesktop/dbus/ExportedObject.java b/org/freedesktop/dbus/ExportedObject.java
index 25d50d9..ecd3d7b 100644
--- a/org/freedesktop/dbus/ExportedObject.java
+++ b/org/freedesktop/dbus/ExportedObject.java
@@ -39,7 +39,7 @@ class ExportedObject
} catch (InvocationTargetException ITe) {
} catch (IllegalAccessException IAe) {}
- ans += " <annotation name=\""+DBusConnection.dollar_pattern.matcher(t.getName()).replaceAll(".")+"\" value=\""+value+"\" />\n";
+ ans += " <annotation name=\""+AbstractConnection.dollar_pattern.matcher(t.getName()).replaceAll(".")+"\" value=\""+value+"\" />\n";
}
return ans;
}
@@ -56,7 +56,7 @@ class ExportedObject
// add this class's public methods
if (c.getName().length() > DBusConnection.MAX_NAME_LENGTH)
throw new DBusException("Introspected interface name exceeds 255 characters. Cannot export objects of type "+c.getName()+".");
- introspectiondata += " <interface name=\""+DBusConnection.dollar_pattern.matcher(c.getName()).replaceAll(".")+"\">\n";
+ introspectiondata += " <interface name=\""+AbstractConnection.dollar_pattern.matcher(c.getName()).replaceAll(".")+"\">\n";
introspectiondata += getAnnotations(c);
for (Method meth: c.getDeclaredMethods())
if (Modifier.isPublic(meth.getModifiers())) {
@@ -68,7 +68,7 @@ class ExportedObject
for (Class ex: meth.getExceptionTypes())
if (DBusExecutionException.class.isAssignableFrom(ex))
introspectiondata +=
- " <annotation name=\"org.freedesktop.DBus.Method.Error\" value=\""+DBusConnection.dollar_pattern.matcher(ex.getName()).replaceAll(".")+"\" />\n";
+ " <annotation name=\"org.freedesktop.DBus.Method.Error\" value=\""+AbstractConnection.dollar_pattern.matcher(ex.getName()).replaceAll(".")+"\" />\n";
for (Type pt: meth.getGenericParameterTypes())
for (String s: Marshalling.getDBusType(pt)) {
introspectiondata += " <arg type=\""+s+"\" direction=\"in\"/>\n";
@@ -127,6 +127,11 @@ class ExportedObject
" <arg type=\"s\" direction=\"out\"/>\n"+
" </method>\n"+
" </interface>\n";
+ introspectiondata +=
+ " <interface name=\"org.freedesktop.DBus.Peer\">\n"+
+ " <method name=\"Ping\">\n"+
+ " </method>\n"+
+ " </interface>\n";
}
}
diff --git a/org/freedesktop/dbus/Marshalling.java b/org/freedesktop/dbus/Marshalling.java
index 1e293a7..a2cd4ab 100644
--- a/org/freedesktop/dbus/Marshalling.java
+++ b/org/freedesktop/dbus/Marshalling.java
@@ -96,9 +96,9 @@ public class Marshalling
if (basic && !(c instanceof Class))
throw new DBusException(c+" is not a basic type");
- if (c instanceof TypeVariable) out[level].append('v');
+ if (c instanceof TypeVariable) out[level].append((char) Message.ArgumentType.VARIANT);
else if (c instanceof GenericArrayType) {
- out[level].append('a');
+ out[level].append((char) Message.ArgumentType.ARRAY);
String[] s = recursiveGetDBusType(((GenericArrayType) c).getGenericComponentType(), false, level+1);
if (s.length != 1) throw new DBusException("Multi-valued array types not permitted");
out[level].append(s[0]);
@@ -116,7 +116,7 @@ public class Marshalling
if (s.length != 1) throw new DBusException("Multi-valued array types not permitted");
out[level].append(s[0]);
} catch (ArrayIndexOutOfBoundsException AIOOBe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, AIOOBe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, AIOOBe);
throw new DBusException("Map must have 2 parameters");
}
out[level].append('}');
@@ -124,20 +124,20 @@ public class Marshalling
else if (List.class.isAssignableFrom((Class) p.getRawType())) {
for (Type t: p.getActualTypeArguments()) {
if (Type.class.equals(t))
- out[level].append('g');
+ out[level].append((char) Message.ArgumentType.SIGNATURE);
else {
String[] s = recursiveGetDBusType(t, false, level+1);
if (s.length != 1) throw new DBusException("Multi-valued array types not permitted");
- out[level].append('a');
+ out[level].append((char) Message.ArgumentType.ARRAY);
out[level].append(s[0]);
}
}
}
else if (p.getRawType().equals(Variant.class)) {
- out[level].append('v');
+ out[level].append((char) Message.ArgumentType.VARIANT);
}
else if (DBusInterface.class.isAssignableFrom((Class) p.getRawType())) {
- out[level].append('o');
+ out[level].append((char) Message.ArgumentType.OBJECT_PATH);
}
else if (Tuple.class.isAssignableFrom((Class) p.getRawType())) {
Type[] ts = p.getActualTypeArguments();
@@ -151,39 +151,43 @@ public class Marshalling
throw new DBusException("Exporting non-exportable parameterized type "+c);
}
- else if (c.equals(Byte.class)) out[level].append('y');
- else if (c.equals(Byte.TYPE)) out[level].append('y');
- else if (c.equals(Boolean.class)) out[level].append('b');
- else if (c.equals(Boolean.TYPE)) out[level].append('b');
- else if (c.equals(Short.class)) out[level].append('n');
- else if (c.equals(Short.TYPE)) out[level].append('n');
- else if (c.equals(UInt16.class)) out[level].append('q');
- else if (c.equals(Integer.class)) out[level].append('i');
- else if (c.equals(Integer.TYPE)) out[level].append('i');
- else if (c.equals(UInt32.class)) out[level].append('u');
- else if (c.equals(Long.class)) out[level].append('x');
- else if (c.equals(Long.TYPE)) out[level].append('x');
- else if (c.equals(UInt64.class)) out[level].append('t');
- else if (c.equals(Double.class)) out[level].append('d');
- else if (c.equals(Double.TYPE)) out[level].append('d');
- else if (c.equals(String.class)) out[level].append('s');
- else if (c.equals(Variant.class)) out[level].append('v');
+ else if (c.equals(Byte.class)) out[level].append((char) Message.ArgumentType.BYTE);
+ else if (c.equals(Byte.TYPE)) out[level].append((char) Message.ArgumentType.BYTE);
+ else if (c.equals(Boolean.class)) out[level].append((char) Message.ArgumentType.BOOLEAN);
+ else if (c.equals(Boolean.TYPE)) out[level].append((char) Message.ArgumentType.BOOLEAN);
+ else if (c.equals(Short.class)) out[level].append((char) Message.ArgumentType.INT16);
+ else if (c.equals(Short.TYPE)) out[level].append((char) Message.ArgumentType.INT16);
+ else if (c.equals(UInt16.class)) out[level].append((char) Message.ArgumentType.UINT16);
+ else if (c.equals(Integer.class)) out[level].append((char) Message.ArgumentType.INT32);
+ else if (c.equals(Integer.TYPE)) out[level].append((char) Message.ArgumentType.INT32);
+ else if (c.equals(UInt32.class)) out[level].append((char) Message.ArgumentType.UINT32);
+ else if (c.equals(Long.class)) out[level].append((char) Message.ArgumentType.INT64);
+ else if (c.equals(Long.TYPE)) out[level].append((char) Message.ArgumentType.INT64);
+ else if (c.equals(UInt64.class)) out[level].append((char) Message.ArgumentType.UINT64);
+ else if (c.equals(Double.class)) out[level].append((char) Message.ArgumentType.DOUBLE);
+ else if (c.equals(Double.TYPE)) out[level].append((char) Message.ArgumentType.DOUBLE);
+ else if (c.equals(Float.class) && AbstractConnection.FLOAT_SUPPORT) out[level].append((char) Message.ArgumentType.FLOAT);
+ else if (c.equals(Float.class)) out[level].append((char) Message.ArgumentType.DOUBLE);
+ else if (c.equals(Float.TYPE) && AbstractConnection.FLOAT_SUPPORT) out[level].append((char) Message.ArgumentType.FLOAT);
+ else if (c.equals(Float.TYPE)) out[level].append((char) Message.ArgumentType.DOUBLE);
+ else if (c.equals(String.class)) out[level].append((char) Message.ArgumentType.STRING);
+ else if (c.equals(Variant.class)) out[level].append((char) Message.ArgumentType.VARIANT);
else if (c instanceof Class &&
- DBusInterface.class.isAssignableFrom((Class) c)) out[level].append('o');
+ DBusInterface.class.isAssignableFrom((Class) c)) out[level].append((char) Message.ArgumentType.OBJECT_PATH);
else if (c instanceof Class &&
- Path.class.equals((Class) c)) out[level].append('o');
+ Path.class.equals((Class) c)) out[level].append((char) Message.ArgumentType.OBJECT_PATH);
else if (c instanceof Class && ((Class) c).isArray()) {
if (Type.class.equals(((Class) c).getComponentType()))
- out[level].append('g');
+ out[level].append((char) Message.ArgumentType.SIGNATURE);
else {
- out[level].append('a');
+ out[level].append((char) Message.ArgumentType.ARRAY);
String[] s = recursiveGetDBusType(((Class) c).getComponentType(), false, level+1);
if (s.length != 1) throw new DBusException("Multi-valued array types not permitted");
out[level].append(s[0]);
}
} else if (c instanceof Class &&
Struct.class.isAssignableFrom((Class) c)) {
- out[level].append('(');
+ out[level].append((char) Message.ArgumentType.STRUCT1);
Type[] ts = Container.getTypeCache(c);
if (null == ts) {
Field[] fs = ((Class) c).getDeclaredFields();
@@ -230,6 +234,8 @@ public class Marshalling
throw new DBusException("Exporting non-exportable type "+c);
}
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Converted Java type: "+c+" to D-Bus Type: "+out[level]);
+
return new String[] { out[level].toString() };
}
@@ -248,11 +254,11 @@ public class Marshalling
int i = 0;
for (; i < dbus.length() && (-1 == limit || limit > rv.size()); i++)
switch(dbus.charAt(i)) {
- case '(':
+ case Message.ArgumentType.STRUCT1:
int j = i+1;
for (int c = 1; c > 0; j++) {
if (')' == dbus.charAt(j)) c--;
- else if ('(' == dbus.charAt(j)) c++;
+ else if (Message.ArgumentType.STRUCT1 == dbus.charAt(j)) c++;
}
Vector<Type> contained = new Vector<Type>();
@@ -260,8 +266,8 @@ public class Marshalling
rv.add(new DBusStructType(contained.toArray(new Type[0])));
i = j;
break;
- case 'a':
- if ('{' == dbus.charAt(i+1)) {
+ case Message.ArgumentType.ARRAY:
+ if (Message.ArgumentType.DICT_ENTRY1 == dbus.charAt(i+1)) {
contained = new Vector<Type>();
c = getJavaType(dbus.substring(i+2), contained, 2);
rv.add(new DBusMapType(contained.get(0), contained.get(1)));
@@ -273,46 +279,49 @@ public class Marshalling
i += c;
}
break;
- case 'v':
+ case Message.ArgumentType.VARIANT:
rv.add(Variant.class);
break;
- case 'b':
+ case Message.ArgumentType.BOOLEAN:
rv.add(Boolean.class);
break;
- case 'n':
+ case Message.ArgumentType.INT16:
rv.add(Short.class);
break;
- case 'y':
+ case Message.ArgumentType.BYTE:
rv.add(Byte.class);
break;
- case 'o':
+ case Message.ArgumentType.OBJECT_PATH:
rv.add(DBusInterface.class);
break;
- case 'q':
+ case Message.ArgumentType.UINT16:
rv.add(UInt16.class);
break;
- case 'i':
+ case Message.ArgumentType.INT32:
rv.add(Integer.class);
break;
- case 'u':
+ case Message.ArgumentType.UINT32:
rv.add(UInt32.class);
break;
- case 'x':
+ case Message.ArgumentType.INT64:
rv.add(Long.class);
break;
- case 't':
+ case Message.ArgumentType.UINT64:
rv.add(UInt64.class);
break;
- case 'd':
+ case Message.ArgumentType.DOUBLE:
rv.add(Double.class);
break;
- case 's':
+ case Message.ArgumentType.FLOAT:
+ rv.add(Float.class);
+ break;
+ case Message.ArgumentType.STRING:
rv.add(String.class);
break;
- case 'g':
+ case Message.ArgumentType.SIGNATURE:
rv.add(Type[].class);
break;
- case '{':
+ case Message.ArgumentType.DICT_ENTRY1:
rv.add(Map.Entry.class);
contained = new Vector<Type>();
c = getJavaType(dbus.substring(i+1), contained, 2);
@@ -323,7 +332,7 @@ public class Marshalling
}
return i;
} catch (IndexOutOfBoundsException IOOBe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOOBe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, IOOBe);
throw new DBusException("Failed to parse DBus type signature: "+dbus);
}
}
@@ -335,7 +344,7 @@ public class Marshalling
* @throws DBusException Thrown if there is an error in converting the objects.
*/
@SuppressWarnings("unchecked")
- public static Object[] convertParameters(Object[] parameters, Type[] types, DBusConnection conn) throws DBusException
+ public static Object[] convertParameters(Object[] parameters, Type[] types, AbstractConnection conn) throws DBusException
{
if (null == parameters) return null;
for (int i = 0; i < parameters.length; i++) {
@@ -384,7 +393,7 @@ public class Marshalling
return parameters;
}
@SuppressWarnings("unchecked")
- static Object deSerializeParameter(Object parameter, Type type, DBusConnection conn) throws Exception
+ static Object deSerializeParameter(Object parameter, Type type, AbstractConnection conn) throws Exception
{
if (null == parameter)
return null;
@@ -450,6 +459,11 @@ public class Marshalling
ts, conn);
}
+ // correct floats if appropriate
+ if (type.equals(Float.class) || type.equals(Float.TYPE))
+ if (!(parameter instanceof Float))
+ parameter = ((Number) parameter).floatValue();
+
// make sure arrays are in the correct format
if (parameter instanceof Object[] ||
parameter instanceof List ||
@@ -470,6 +484,14 @@ public class Marshalling
} else if (type instanceof Class &&
((Class) type).isArray()) {
Class cc = ((Class) type).getComponentType();
+ if ((cc.equals(Float.class) || cc.equals(Float.TYPE))
+ && (parameter instanceof double[])) {
+ double[] tmp1 = (double[]) parameter;
+ float[] tmp2 = new float[tmp1.length];
+ for (int i = 0; i < tmp1.length; i++)
+ tmp2[i] = (float) tmp1[i];
+ parameter = tmp2;
+ }
Object o = Array.newInstance(cc, 0);
parameter = ArrayFrob.convert(parameter,
o.getClass());
@@ -477,7 +499,7 @@ public class Marshalling
}
return parameter;
}
- static Object[] deSerializeParameters(Object[] parameters, Type[] types, DBusConnection conn) throws Exception
+ static Object[] deSerializeParameters(Object[] parameters, Type[] types, AbstractConnection conn) throws Exception
{
if (null == parameters) return null;
for (int i = 0; i < parameters.length; i++) {
@@ -501,7 +523,7 @@ public class Marshalling
System.arraycopy(parameters, i + newtypes.length, compress, i+1, parameters.length - i - newtypes.length);
parameters = compress;
} catch (ArrayIndexOutOfBoundsException AIOOBe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, AIOOBe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, AIOOBe);
throw new DBusException("Not enough elements to create custom object from serialized data ("+(parameters.length-i)+" < "+(newtypes.length)+")");
}
}
diff --git a/org/freedesktop/dbus/Message.java b/org/freedesktop/dbus/Message.java
index 138bb14..3666818 100644
--- a/org/freedesktop/dbus/Message.java
+++ b/org/freedesktop/dbus/Message.java
@@ -174,6 +174,7 @@ public class Message
big = (Endian.BIG == endian);
bytecounter = 0;
serial = ++globalserial;
+ if (Debug.debug) Debug.print(Debug.DEBUG, "Creating message with serial "+serial);
this.type = type;
this.flags = flags;
preallocate(4);
@@ -408,7 +409,7 @@ public class Message
try {
args = getParameters();
} catch (DBusException DBe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
}
if (null == args || 0 == args.length)
sb.append('}');
@@ -473,11 +474,11 @@ public class Message
appendint(((Boolean) data).booleanValue() ? 1 : 0, 4);
break;
case ArgumentType.DOUBLE:
- long l = Double.doubleToLongBits((Double) data);
+ long l = Double.doubleToLongBits(((Number) data).doubleValue());
appendint(l, 8);
break;
case ArgumentType.FLOAT:
- int rf = Float.floatToIntBits((Float) data);
+ int rf = Float.floatToIntBits(((Number) data).floatValue());
appendint(rf, 4);
break;
case ArgumentType.UINT32:
@@ -513,7 +514,7 @@ public class Message
try {
payloadbytes = payload.getBytes("UTF-8");
} catch (UnsupportedEncodingException UEe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(UEe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(UEe);
throw new DBusException("System does not support UTF-8 encoding");
}
if (Debug.debug) Debug.print(Debug.VERBOSE, "Appending String of length "+payloadbytes.length);
@@ -576,10 +577,14 @@ public class Message
break;
case ArgumentType.DOUBLE:
primbuf = new byte[len*algn];
- for (int j = 0, k = 0; j < len; j++, k += algn)
- marshallint(
- Double.doubleToRawLongBits(((double[])data)[j]),
- primbuf, k, algn);
+ if (data instanceof float[])
+ for (int j = 0, k = 0; j < len; j++, k += algn)
+ marshallint(Double.doubleToRawLongBits(((float[])data)[j]),
+ primbuf, k, algn);
+ else
+ for (int j = 0, k = 0; j < len; j++, k += algn)
+ marshallint(Double.doubleToRawLongBits(((double[])data)[j]),
+ primbuf, k, algn);
break;
case ArgumentType.FLOAT:
primbuf = new byte[len*algn];
@@ -670,7 +675,7 @@ public class Message
}
return i;
} catch (ClassCastException CCe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, CCe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, CCe);
throw new MarshallingException("Trying to marshall to unconvertable type (from "+data.getClass().getName()+" to "+sigb[sigofs]+")");
}
}
@@ -948,7 +953,7 @@ public class Message
try {
rv = new String(buf, ofs[1], length, "UTF-8");
} catch (UnsupportedEncodingException UEe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(UEe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(UEe);
throw new DBusException("System does not support UTF-8 encoding");
}
ofs[1] += length + 1;
diff --git a/org/freedesktop/dbus/MessageReader.java b/org/freedesktop/dbus/MessageReader.java
index 75aa1de..d90d3df 100644
--- a/org/freedesktop/dbus/MessageReader.java
+++ b/org/freedesktop/dbus/MessageReader.java
@@ -135,14 +135,14 @@ public class MessageReader
try {
m.populate(buf, header, body);
} catch (DBusException DBe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
buf = null;
tbuf = null;
body = null;
header = null;
throw DBe;
} catch (RuntimeException Re) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, Re);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, Re);
buf = null;
tbuf = null;
body = null;
diff --git a/org/freedesktop/dbus/MethodCall.java b/org/freedesktop/dbus/MethodCall.java
index c275d84..75d333a 100644
--- a/org/freedesktop/dbus/MethodCall.java
+++ b/org/freedesktop/dbus/MethodCall.java
@@ -23,16 +23,19 @@ public class MethodCall extends Message
{
super(Message.Endian.BIG, Message.MessageType.METHOD_CALL, flags);
- if (null == dest || null == member || null == path)
+ if (null == member || null == path)
throw new MessageFormatException("Must specify destination, path and function name to MethodCalls.");
headers.put(Message.HeaderField.PATH,path);
- headers.put(Message.HeaderField.DESTINATION,dest);
headers.put(Message.HeaderField.MEMBER,member);
Vector<Object> hargs = new Vector<Object>();
hargs.add(new Object[] { Message.HeaderField.PATH, new Object[] { ArgumentType.OBJECT_PATH_STRING, path } });
- hargs.add(new Object[] { Message.HeaderField.DESTINATION, new Object[] { ArgumentType.STRING_STRING, dest } });
+
+ if (null != dest) {
+ headers.put(Message.HeaderField.DESTINATION,dest);
+ hargs.add(new Object[] { Message.HeaderField.DESTINATION, new Object[] { ArgumentType.STRING_STRING, dest } });
+ }
if (null != iface) {
hargs.add(new Object[] { Message.HeaderField.INTERFACE, new Object[] { ArgumentType.STRING_STRING, iface } });
diff --git a/org/freedesktop/dbus/MethodReturn.java b/org/freedesktop/dbus/MethodReturn.java
index 8fcb4b9..26799a5 100644
--- a/org/freedesktop/dbus/MethodReturn.java
+++ b/org/freedesktop/dbus/MethodReturn.java
@@ -21,15 +21,16 @@ public class MethodReturn extends Message
{
super(Message.Endian.BIG, Message.MessageType.METHOD_RETURN, (byte) 0);
- if (null == dest)
- throw new MessageFormatException("Must specify destination to Method Returns.");
- headers.put(Message.HeaderField.DESTINATION,dest);
headers.put(Message.HeaderField.REPLY_SERIAL,replyserial);
Vector<Object> hargs = new Vector<Object>();
- hargs.add(new Object[] { Message.HeaderField.DESTINATION, new Object[] { ArgumentType.STRING_STRING, dest } });
hargs.add(new Object[] { Message.HeaderField.REPLY_SERIAL, new Object[] { ArgumentType.UINT32_STRING, replyserial } });
+ if (null != dest) {
+ headers.put(Message.HeaderField.DESTINATION,dest);
+ hargs.add(new Object[] { Message.HeaderField.DESTINATION, new Object[] { ArgumentType.STRING_STRING, dest } });
+ }
+
if (null != sig) {
hargs.add(new Object[] { Message.HeaderField.SIGNATURE, new Object[] { ArgumentType.SIGNATURE_STRING, sig } });
headers.put(Message.HeaderField.SIGNATURE,sig);
@@ -38,7 +39,7 @@ public class MethodReturn extends Message
byte[] blen = new byte[4];
appendBytes(blen);
- append("ua(yv)", ++serial, hargs.toArray());
+ append("ua(yv)", serial, hargs.toArray());
pad((byte)8);
long c = bytecounter;
diff --git a/org/freedesktop/dbus/RemoteInvocationHandler.java b/org/freedesktop/dbus/RemoteInvocationHandler.java
index ce10bde..ee70984 100644
--- a/org/freedesktop/dbus/RemoteInvocationHandler.java
+++ b/org/freedesktop/dbus/RemoteInvocationHandler.java
@@ -30,7 +30,7 @@ import cx.ath.matthew.debug.Debug;
class RemoteInvocationHandler implements InvocationHandler
{
- public static Object convertRV(String sig, Object[] rp, Method m, DBusConnection conn) throws DBusException
+ public static Object convertRV(String sig, Object[] rp, Method m, AbstractConnection conn) throws DBusException
{
Class c = m.getReturnType();
@@ -50,7 +50,7 @@ class RemoteInvocationHandler implements InvocationHandler
new Type[] { m.getGenericReturnType() }, conn);
}
catch (Exception e) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
throw new DBusExecutionException("Wrong return type (failed to de-serialize correct types: "+e.getMessage()+")");
}
@@ -63,19 +63,19 @@ class RemoteInvocationHandler implements InvocationHandler
try {
rp = Marshalling.deSerializeParameters(rp, ((ParameterizedType) m.getGenericReturnType()).getActualTypeArguments(), conn);
} catch (Exception e) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
throw new DBusExecutionException("Wrong return type (failed to de-serialize correct types: "+e.getMessage()+")");
}
Constructor cons = c.getConstructors()[0];
try {
return cons.newInstance(rp);
} catch (Exception e) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
throw new DBusException(e.getMessage());
}
}
}
- public static Object executeRemoteMethod(RemoteObject ro, Method m, DBusConnection conn, boolean async, Object... args) throws DBusExecutionException
+ public static Object executeRemoteMethod(RemoteObject ro, Method m, AbstractConnection conn, boolean async, Object... args) throws DBusExecutionException
{
Type[] ts = m.getGenericParameterTypes();
String sig = null;
@@ -94,13 +94,14 @@ class RemoteInvocationHandler implements InvocationHandler
if (null == ro.iface)
call = new MethodCall(ro.busname, ro.objectpath, null, m.getName(),flags, sig, args);
else
- call = new MethodCall(ro.busname, ro.objectpath, DBusConnection.dollar_pattern.matcher(ro.iface.getName()).replaceAll("."), m.getName(), flags, sig, args);
+ call = new MethodCall(ro.busname, ro.objectpath, AbstractConnection.dollar_pattern.matcher(ro.iface.getName()).replaceAll("."), m.getName(), flags, sig, args);
} catch (DBusException DBe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
throw new DBusExecutionException("Failed to construct outgoing method call: "+DBe.getMessage());
}
if (null == conn.outgoing) throw new NotConnected("Not Connected");
synchronized (conn.outgoing) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Adding method call to outgoing queue");
conn.outgoing.add(call);
}
@@ -118,14 +119,14 @@ class RemoteInvocationHandler implements InvocationHandler
try {
return convertRV(reply.getSig(), reply.getParameters(), m, conn);
} catch (DBusException e) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
throw new DBusExecutionException(e.getMessage());
}
}
- DBusConnection conn;
+ AbstractConnection conn;
RemoteObject remote;
- public RemoteInvocationHandler(DBusConnection conn, RemoteObject remote)
+ public RemoteInvocationHandler(AbstractConnection conn, RemoteObject remote)
{
this.remote = remote;
this.conn = conn;
diff --git a/org/freedesktop/dbus/RemoteObject.java b/org/freedesktop/dbus/RemoteObject.java
index 8460586..46b7025 100644
--- a/org/freedesktop/dbus/RemoteObject.java
+++ b/org/freedesktop/dbus/RemoteObject.java
@@ -27,14 +27,22 @@ class RemoteObject
{
if (!(o instanceof RemoteObject)) return false;
RemoteObject them = (RemoteObject) o;
- if (!them.busname.equals(this.busname)) return false;
+
if (!them.objectpath.equals(this.objectpath)) return false;
- if (null != this.iface && !them.iface.equals(this.iface)) return false;
+
+ if (null == this.busname && null != them.busname) return false;
+ if (null != this.busname && null == them.busname) return false;
+ if (null != them.busname && !them.busname.equals(this.busname)) return false;
+
+ if (null == this.iface && null != them.iface) return false;
+ if (null != this.iface && null == them.iface) return false;
+ if (null != them.iface && !them.iface.equals(this.iface)) return false;
+
return true;
}
public int hashCode()
{
- return busname.hashCode() + objectpath.hashCode() +
+ return (null == busname ? 0 : busname.hashCode()) + objectpath.hashCode() +
(null == iface ? 0 : iface.hashCode());
}
public boolean autoStarting() { return autostart; }
diff --git a/org/freedesktop/dbus/Transport.java b/org/freedesktop/dbus/Transport.java
index 783f173..159046c 100644
--- a/org/freedesktop/dbus/Transport.java
+++ b/org/freedesktop/dbus/Transport.java
@@ -10,14 +10,18 @@
*/
package org.freedesktop.dbus;
-import java.net.InetSocketAddress;
-import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.text.Collator;
+import java.util.Random;
import cx.ath.matthew.unix.UnixSocket;
+import cx.ath.matthew.unix.UnixServerSocket;
import cx.ath.matthew.unix.UnixSocketAddress;
import cx.ath.matthew.utils.Hexdump;
import cx.ath.matthew.debug.Debug;
@@ -29,6 +33,14 @@ public class Transport
public MessageReader min;
public MessageWriter mout;
public Transport() {}
+ public static String genGUID()
+ {
+ Random r = new Random();
+ byte[] buf = new byte[16];
+ r.nextBytes(buf);
+ String guid = Hexdump.toHex(buf);
+ return guid.replaceAll(" ", "");
+ }
public Transport(BusAddress address) throws IOException
{
connect(address);
@@ -42,23 +54,45 @@ public class Transport
out.write(new byte[] { 0 });
BufferedReader r = new BufferedReader(new InputStreamReader(in));
if ("unix".equals(address.getType())) {
- UnixSystem uns = new UnixSystem();
- long uid = uns.getUid();
- String Uid = Hexdump.toHex((""+uid).getBytes()).replaceAll(" ","");
- out.write(("AUTH EXTERNAL "+Uid+"\r\n").getBytes());
- if (Debug.debug) Debug.print(Debug.VERBOSE, "AUTH EXTERNAL "+Uid+"\r\n");
+ if (null == address.getParameter("listen")) {
+ UnixSystem uns = new UnixSystem();
+ long uid = uns.getUid();
+ String Uid = Hexdump.toHex((""+uid).getBytes()).replaceAll(" ","");
+ out.write(("AUTH EXTERNAL "+Uid+"\r\n").getBytes());
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "AUTH EXTERNAL "+Uid+"\r\n");
+ } else {
+ String s = r.readLine();
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "reading:"+s);
+ String guid = address.getParameter("guid");
+ if (null == guid) guid = genGUID();
+ out.write(("OK "+guid+"\r\n").getBytes());
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "OK "+guid);
+ s = r.readLine();
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "reading"+s);
+ if ("BEGIN".equals(s)) return true;
+ }
} else {
out.write(("AUTH DBUS_COOKIE_SHA1\r\n").getBytes());
}
String s = r.readLine();
if (Debug.debug) Debug.print(Debug.VERBOSE, s);
String[] reply=s.split(" ");
- if (!"OK".equals(reply[0])) return false;
- if (null == address.getParameter("guid") || reply[1].equals(address.getParameter("guid"))) {
+ Collator col = Collator.getInstance();
+ col.setDecomposition(Collator.FULL_DECOMPOSITION);
+ col.setStrength(Collator.PRIMARY);
+ if (0 != col.compare("OK", reply[0])) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "reply[0] = `"+reply[0]+"'");
+ return false;
+ }
+ if (null == address.getParameter("guid") || (reply.length > 1 && reply[1].equals(address.getParameter("guid")))) {
if (Debug.debug) Debug.print(Debug.VERBOSE, "BEGIN\r\n");
out.write("BEGIN\r\n".getBytes());
return true;
- }
+ } else if (Debug.debug)
+ if (reply.length == 1)
+ Debug.print(Debug.ERR, "GUID Mismatch, expecting: "+address.getParameter("guid")+", got no guid");
+ else
+ Debug.print(Debug.ERR, "GUID Mismatch, expecting: "+address.getParameter("guid")+", got: "+reply[1]);
return false;
}
public void connect(String address) throws IOException
@@ -71,19 +105,36 @@ public class Transport
this.address = address;
OutputStream out = null;
InputStream in = null;
+ UnixSocket us = null;
if ("unix".equals(address.getType())) {
- UnixSocket us = new UnixSocket();
- us.setBlocking(false);
- if (null != address.getParameter("abstract"))
- us.connect(new UnixSocketAddress(address.getParameter("abstract"), true));
- else if (null != address.getParameter("path"))
- us.connect(new UnixSocketAddress(address.getParameter("path"), false));
+ if (null != address.getParameter("listen")) {
+ UnixServerSocket uss = new UnixServerSocket();
+ if (null != address.getParameter("abstract"))
+ uss.bind(new UnixSocketAddress(address.getParameter("abstract"), true));
+ else if (null != address.getParameter("path"))
+ uss.bind(new UnixSocketAddress(address.getParameter("path"), false));
+ us = uss.accept();
+ } else {
+ us = new UnixSocket();
+ if (null != address.getParameter("abstract"))
+ us.connect(new UnixSocketAddress(address.getParameter("abstract"), true));
+ else if (null != address.getParameter("path"))
+ us.connect(new UnixSocketAddress(address.getParameter("path"), false));
+ }
us.setPassCred(true);
in = us.getInputStream();
out = us.getOutputStream();
} else if ("tcp".equals(address.getType())) {
- Socket s = new Socket();
- s.connect(new InetSocketAddress(address.getParameter("host"), Integer.parseInt(address.getParameter("port"))));
+ Socket s = null;
+ if (null != address.getParameter("listen")) {
+ ServerSocket ss = new ServerSocket();
+ ss.bind(new InetSocketAddress(address.getParameter("host"), Integer.parseInt(address.getParameter("port"))));
+ s = ss.accept();
+ } else {
+ s = new Socket();
+ s.connect(new InetSocketAddress(address.getParameter("host"), Integer.parseInt(address.getParameter("port"))));
+ }
+ s.setSoTimeout(0);
in = s.getInputStream();
out = s.getOutputStream();
} else {
@@ -95,6 +146,10 @@ public class Transport
out.close();
throw new IOException("Failed to auth");
}
+ if (null != us) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Setting non-blocking on UnixSocket");
+ us.setBlocking(false);
+ }
mout = new MessageWriter(out);
min = new MessageReader(in);
}
diff --git a/org/freedesktop/dbus/Variant.java b/org/freedesktop/dbus/Variant.java
index d0bbf52..73b52d0 100644
--- a/org/freedesktop/dbus/Variant.java
+++ b/org/freedesktop/dbus/Variant.java
@@ -42,7 +42,7 @@ public class Variant<T>
throw new IllegalArgumentException("Can't wrap a multi-valued type in a Variant ("+type+")");
this.sig = ss[0];
} catch (DBusException DBe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
throw new IllegalArgumentException("Can't wrap "+o.getClass()+" in an unqualified Variant ("+DBe.getMessage()+")");
}
this.o = o;
@@ -63,7 +63,7 @@ public class Variant<T>
throw new IllegalArgumentException("Can't wrap a multi-valued type in a Variant ("+type+")");
this.sig = ss[0];
} catch (DBusException DBe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
throw new IllegalArgumentException("Can't wrap a "+type+" in a Variant ("+DBe.getMessage()+")");
}
this.o = o;
@@ -85,7 +85,7 @@ public class Variant<T>
throw new IllegalArgumentException("Can't wrap multiple or no types in a Variant ("+sig+")");
this.type = ts.get(0);
} catch (DBusException DBe) {
- if (DBusConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
+ if (AbstractConnection.EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
throw new IllegalArgumentException("Can't wrap a "+sig+" in a Variant ("+DBe.getMessage()+")");
}
this.o = o;
diff --git a/org/freedesktop/dbus/exceptions/FatalDBusException.java b/org/freedesktop/dbus/exceptions/FatalDBusException.java
new file mode 100644
index 0000000..3fca524
--- /dev/null
+++ b/org/freedesktop/dbus/exceptions/FatalDBusException.java
@@ -0,0 +1,20 @@
+/*
+ D-Bus Java Implementation
+ Copyright (c) 2005-2006 Matthew Johnson
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of either the GNU General Public License Version 2 or the
+ Academic Free Licence Version 2.1.
+
+ Full licence texts are included in the COPYING file with this program.
+*/
+package org.freedesktop.dbus.exceptions;
+
+@SuppressWarnings("serial")
+public class FatalDBusException extends DBusException implements FatalException
+{
+ public FatalDBusException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/org/freedesktop/dbus/exceptions/InternalMessageException.java b/org/freedesktop/dbus/exceptions/InternalMessageException.java
index 03b0a9e..ff6e80f 100644
--- a/org/freedesktop/dbus/exceptions/InternalMessageException.java
+++ b/org/freedesktop/dbus/exceptions/InternalMessageException.java
@@ -11,7 +11,7 @@
package org.freedesktop.dbus.exceptions;
@SuppressWarnings("serial")
-public class InternalMessageException extends DBusExecutionException
+public class InternalMessageException extends DBusExecutionException implements NonFatalException
{
public InternalMessageException(String message)
{
diff --git a/org/freedesktop/dbus/exceptions/NotConnected.java b/org/freedesktop/dbus/exceptions/NotConnected.java
index 9b6f553..2367209 100644
--- a/org/freedesktop/dbus/exceptions/NotConnected.java
+++ b/org/freedesktop/dbus/exceptions/NotConnected.java
@@ -14,7 +14,7 @@ package org.freedesktop.dbus.exceptions;
* Thrown if a DBus action is called when not connected to the Bus.
*/
@SuppressWarnings("serial")
-public class NotConnected extends DBusExecutionException
+public class NotConnected extends DBusExecutionException implements FatalException
{
public NotConnected(String message)
{
diff --git a/org/freedesktop/dbus/test/TestRemoteInterface.java b/org/freedesktop/dbus/test/TestRemoteInterface.java
index 03a042e..6556071 100644
--- a/org/freedesktop/dbus/test/TestRemoteInterface.java
+++ b/org/freedesktop/dbus/test/TestRemoteInterface.java
@@ -43,4 +43,6 @@ public interface TestRemoteInterface extends DBusInterface
public void sig(Type[] s);
@Description("Testing object paths as Path objects")
public void newpathtest(Path p);
+ @Description("Testing the float type")
+ public float testfloat(float[] f);
}
diff --git a/org/freedesktop/dbus/test/test.java b/org/freedesktop/dbus/test/test.java
index 18d85c1..29e6c0c 100644
--- a/org/freedesktop/dbus/test/test.java
+++ b/org/freedesktop/dbus/test/test.java
@@ -59,6 +59,16 @@ class testclass implements TestRemoteInterface, TestRemoteInterface2, TestSignal
{
this.conn = conn;
}
+ public float testfloat(float[] f)
+ {
+ if (f.length < 4 ||
+ f[0] != 17.093f ||
+ f[1] != -23f ||
+ f[2] != 0.0f ||
+ f[3] != 31.42f)
+ test.fail("testfloat got incorrect array");
+ return f[0];
+ }
public void newpathtest(Path p)
{
if (!p.toString().equals("/new/path/test"))
@@ -438,6 +448,9 @@ public class test
fail("getName return value incorrect");
System.out.println("sending it to sleep");
tri.waitawhile();
+ System.out.println("testing floats");
+ if (17.093f != tri.testfloat(new float[] { 17.093f, -23f, 0.0f, 31.42f }))
+ fail("testfloat returned the wrong thing");
System.out.println("frobnicating");
List<Long> ls = new Vector<Long>();
ls.add(2L);
diff --git a/org/freedesktop/dbus/test/test_p2p_client.java b/org/freedesktop/dbus/test/test_p2p_client.java
new file mode 100644
index 0000000..aa6d64f
--- /dev/null
+++ b/org/freedesktop/dbus/test/test_p2p_client.java
@@ -0,0 +1,42 @@
+/*
+ D-Bus Java Implementation
+ Copyright (c) 2005-2006 Matthew Johnson
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of either the GNU General Public License Version 2 or the
+ Academic Free Licence Version 2.1.
+
+ Full licence texts are included in the COPYING file with this program.
+*/
+package org.freedesktop.dbus.test;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+
+import org.freedesktop.DBus;
+import org.freedesktop.dbus.DirectConnection;
+
+public class test_p2p_client
+{
+ public static void main(String[] args) throws Exception
+ {
+ BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream("address")));
+ String address = r.readLine();
+ DirectConnection dc = new DirectConnection(address);
+ System.out.println("Connected");
+ TestRemoteInterface tri = (TestRemoteInterface) dc.getRemoteObject("/Test");
+ System.out.println(tri.getName());
+ System.out.println(tri.testfloat(new float[] { 17.093f, -23f, 0.0f, 31.42f }));
+
+ try {
+ tri.throwme();
+ } catch (TestException Te) {
+ System.out.println("Caught TestException");
+ }
+ ((DBus.Peer) tri).Ping();
+ System.out.println(((DBus.Introspectable) tri).Introspect());
+ dc.disconnect();
+ System.out.println("Disconnected");
+ }
+}
diff --git a/org/freedesktop/dbus/test/test_p2p_server.java b/org/freedesktop/dbus/test/test_p2p_server.java
new file mode 100644
index 0000000..04c0856
--- /dev/null
+++ b/org/freedesktop/dbus/test/test_p2p_server.java
@@ -0,0 +1,72 @@
+/*
+ D-Bus Java Implementation
+ Copyright (c) 2005-2006 Matthew Johnson
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of either the GNU General Public License Version 2 or the
+ Academic Free Licence Version 2.1.
+
+ Full licence texts are included in the COPYING file with this program.
+*/
+package org.freedesktop.dbus.test;
+
+import java.lang.reflect.Type;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.freedesktop.dbus.DirectConnection;
+import org.freedesktop.dbus.Path;
+import org.freedesktop.dbus.UInt16;
+
+public class test_p2p_server implements TestRemoteInterface
+{
+ public String getName()
+ {
+ System.out.println("getName called");
+ return "Peer2Peer Server";
+ }
+ public <T> int frobnicate(List<Long> n, Map<String,Map<UInt16,Short>> m, T v)
+ {
+ return 3;
+ }
+ public void throwme() throws TestException
+ {
+ System.out.println("throwme called");
+ throw new TestException("BOO");
+ }
+ public void waitawhile()
+ {
+ return;
+ }
+ public int overload()
+ {
+ return 1;
+ }
+ public void sig(Type[] s)
+ {
+ }
+ public void newpathtest(Path p)
+ {
+ }
+ public boolean isRemote() { return false; }
+ public float testfloat(float[] f)
+ {
+ System.out.println("got float: "+Arrays.toString(f));
+ return f[0];
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ String address = DirectConnection.createDynamicSession();
+ PrintWriter w = new PrintWriter(new FileOutputStream("address"));
+ w.println(address.replaceAll("listen=true,",""));
+ w.flush();
+ w.close();
+ DirectConnection dc = new DirectConnection(address);
+ System.out.println("Connected");
+ dc.exportObject("/Test", new test_p2p_server());
+ }
+}