summaryrefslogtreecommitdiff
path: root/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/AbstractConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/AbstractConnection.java')
-rwxr-xr-xsrc/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/AbstractConnection.java1075
1 files changed, 1075 insertions, 0 deletions
diff --git a/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/AbstractConnection.java b/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/AbstractConnection.java
new file mode 100755
index 0000000..3c2607e
--- /dev/null
+++ b/src/traffic-incidents-service/org.genivi.trafficinfo.dbus-java/src/main/java/org/freedesktop/dbus/AbstractConnection.java
@@ -0,0 +1,1075 @@
+/*
+ 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 Lesser 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 static org.freedesktop.dbus.Gettext._;
+
+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.text.MessageFormat;
+import java.text.ParseException;
+
+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 cx.ath.matthew.debug.Debug;
+
+
+/** Handles a connection to DBus.
+ */
+public abstract class AbstractConnection
+{
+ protected class FallbackContainer
+ {
+ private Map<String[], ExportedObject> fallbacks = new HashMap<String[], ExportedObject>();
+ public synchronized void add(String path, ExportedObject eo)
+ {
+ if (Debug.debug) Debug.print(Debug.DEBUG, "Adding fallback on "+path+" of "+eo);
+ fallbacks.put(path.split("/"), eo);
+ }
+ public synchronized void remove(String path)
+ {
+ if (Debug.debug) Debug.print(Debug.DEBUG, "Removing fallback on "+path);
+ fallbacks.remove(path.split("/"));
+ }
+ public synchronized ExportedObject get(String path)
+ {
+ int best = 0;
+ int i = 0;
+ ExportedObject bestobject = null;
+ String[] pathel = path.split("/");
+ for (String[] fbpath: fallbacks.keySet()) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Trying fallback path "+Arrays.deepToString(fbpath)+" to match "+Arrays.deepToString(pathel));
+ for (i = 0; i < pathel.length && i < fbpath.length; i++)
+ if (!pathel[i].equals(fbpath[i])) break;
+ if (i > 0 && i == fbpath.length && i > best)
+ bestobject = fallbacks.get(fbpath);
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Matches "+i+" bestobject now "+bestobject);
+ }
+ if (Debug.debug) Debug.print(Debug.DEBUG, "Found fallback for "+path+" of "+bestobject);
+ return bestobject;
+ }
+ }
+ protected class _thread extends Thread
+ {
+ public _thread()
+ {
+ 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();
+ 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) {
+ e.printStackTrace();
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (e instanceof FatalException) {
+ disconnect();
+ }
+ }
+
+ }
+ synchronized (this) { notifyAll(); }
+ } catch (Exception e) {
+ e.printStackTrace();
+ if (Debug.debug && EXCEPTION_DEBUG) Debug.print(Debug.ERR, e);
+ }
+ }
+ }
+ 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) {
+ ExportedObject eo = fallbackcontainer.get(objectpath);
+ if (null != eo) intro = eo.introspectiondata;
+ }
+ 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();
+ }
+ }
+ }
+ private class _sender extends Thread
+ {
+ public _sender()
+ {
+ setName("Sender");
+ }
+ public void run()
+ {
+ Message m = null;
+
+ if (Debug.debug) Debug.print(Debug.INFO, "Monitoring outbound queue");
+ // block on the outbound queue and send from it
+ while (_run) {
+ if (null != outgoing) synchronized (outgoing) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Blocking");
+ while (outgoing.size() == 0 && _run)
+ try { outgoing.wait(); } catch (InterruptedException Ie) {}
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Notified");
+ if (outgoing.size() > 0)
+ m = outgoing.remove();
+ if (Debug.debug) Debug.print(Debug.DEBUG, "Got message: "+m);
+ }
+ if (null != m)
+ sendMessage(m);
+ m = null;
+ }
+
+ if (Debug.debug) Debug.print(Debug.INFO, "Flushing outbound queue and quitting");
+ // flush the outbound queue before disconnect.
+ if (null != outgoing) do {
+ EfficientQueue ogq = outgoing;
+ synchronized (ogq) {
+ outgoing = null;
+ }
+ if (!ogq.isEmpty())
+ m = ogq.remove();
+ else m = null;
+ sendMessage(m);
+ } while (null != m);
+
+ // close the underlying streams
+ }
+ }
+ /**
+ * Timeout in us on checking the BUS for incoming messages and sending outgoing messages
+ */
+ protected static final int TIMEOUT = 100000;
+ /** 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 String currentSender = null; // pego
+
+ protected Map<String,ExportedObject> exportedObjects;
+ private ObjectTree objectTree;
+ private _globalhandler _globalhandlerreference;
+ protected Map<DBusInterface,RemoteObject> importedObjects;
+ protected Map<SignalTuple,Vector<DBusSigHandler<? extends DBusSignal>>> handledSignals;
+ protected EfficientMap pendingCalls;
+ protected Map<MethodCall, CallbackHandler<? extends Object>> pendingCallbacks;
+ protected Map<MethodCall, DBusAsyncReply<? extends Object>> pendingCallbackReplys;
+ protected LinkedList<Runnable> runnables;
+ protected LinkedList<_workerthread> workers;
+ protected FallbackContainer fallbackcontainer;
+ protected boolean _run;
+ EfficientQueue outgoing;
+ LinkedList<Error> pendingErrors;
+ private static final Map<Thread,DBusCallInfo> infomap = new HashMap<Thread,DBusCallInfo>();
+ protected _thread thread;
+ protected _sender sender;
+ protected Transport transport;
+ protected String addr;
+ protected boolean weakreferences = false;
+ static final Pattern dollar_pattern = Pattern.compile("[$]");
+ public static final boolean EXCEPTION_DEBUG;
+ static final boolean FLOAT_SUPPORT;
+ protected boolean connected = false;
+ 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>();
+ _globalhandlerreference = new _globalhandler();
+ synchronized (exportedObjects) {
+ exportedObjects.put(null, new ExportedObject(_globalhandlerreference, weakreferences));
+ }
+ handledSignals = new HashMap<SignalTuple,Vector<DBusSigHandler<? extends DBusSignal>>>();
+ pendingCalls = new EfficientMap(PENDING_MAP_INITIAL_SIZE);
+ outgoing = new EfficientQueue(PENDING_MAP_INITIAL_SIZE);
+ pendingCallbacks = new HashMap<MethodCall, CallbackHandler<? extends Object>>();
+ pendingCallbackReplys = new HashMap<MethodCall, DBusAsyncReply<? extends Object>>();
+ pendingErrors = new LinkedList<Error>();
+ runnables = new LinkedList<Runnable>();
+ workers = new LinkedList<_workerthread>();
+ objectTree = new ObjectTree();
+ fallbackcontainer = new FallbackContainer();
+ 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();
+ sender = new _sender();
+ sender.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
+ {
+ synchronized (exportedObjects) {
+ for (String s: exportedObjects.keySet())
+ if (i.equals(exportedObjects.get(s).object.get()))
+ return s;
+ }
+
+ String s = importedObjects.get(i).objectpath;
+ if (null != s) return s;
+
+ 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;
+ }
+
+ /**
+ * If set to true the bus will not hold a strong reference to exported objects.
+ * If they go out of scope they will automatically be unexported from the bus.
+ * The default is to hold a strong reference, which means objects must be
+ * explicitly unexported before they will be garbage collected.
+ */
+ public void setWeakReferences(boolean weakreferences)
+ {
+ this.weakreferences = weakreferences;
+ }
+
+ /**
+ * 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 (null == objectpath || "".equals(objectpath))
+ throw new DBusException(_("Must Specify an Object Path"));
+ if (!objectpath.matches(OBJECT_REGEX)||objectpath.length() > MAX_NAME_LENGTH)
+ throw new DBusException(_("Invalid object path: ")+objectpath);
+ synchronized (exportedObjects) {
+ if (null != exportedObjects.get(objectpath))
+ throw new DBusException(_("Object already exported"));
+ ExportedObject eo = new ExportedObject(object, weakreferences);
+ exportedObjects.put(objectpath, eo);
+ objectTree.add(objectpath, eo, eo.introspectiondata);
+ }
+ }
+ /**
+ * Export an object as a fallback object.
+ * This object will have it's methods invoked for all paths starting
+ * with this object path.
+ * @param objectprefix The path below which the fallback handles calls.
+ * MUST be in slash-notation, like "/org/freedesktop/Local",
+ * @param object The object to export.
+ * @throws DBusException If the objectpath is incorrectly formatted,
+ */
+ public void addFallback(String objectprefix, DBusInterface object) throws DBusException
+ {
+ if (null == objectprefix || "".equals(objectprefix))
+ throw new DBusException(_("Must Specify an Object Path"));
+ if (!objectprefix.matches(OBJECT_REGEX)||objectprefix.length() > MAX_NAME_LENGTH)
+ throw new DBusException(_("Invalid object path: ")+objectprefix);
+ ExportedObject eo = new ExportedObject(object, weakreferences);
+ fallbackcontainer.add(objectprefix, eo);
+ }
+ /**
+ * Remove a fallback
+ * @param objectprefix The prefix to remove the fallback for.
+ */
+ public void removeFallback(String objectprefix)
+ {
+ fallbackcontainer.remove(objectprefix);
+ }
+ /**
+ * Stop Exporting an object
+ * @param objectpath The objectpath to stop exporting.
+ */
+ public void unExportObject(String objectpath)
+ {
+ synchronized (exportedObjects) {
+ exportedObjects.remove(objectpath);
+ objectTree.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)
+ {
+ queueOutgoing(signal);
+ }
+ void queueOutgoing(Message m)
+ {
+ synchronized (outgoing) {
+ if (null == outgoing) return;
+ outgoing.add(m);
+ if (Debug.debug) Debug.print(Debug.DEBUG, "Notifying outgoing thread");
+ outgoing.notifyAll();
+ }
+ }
+ /**
+ * 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.
+ */
+ @SuppressWarnings("unchecked")
+ 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), (DBusSigHandler<? extends DBusSignal>) 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.
+ */
+ @SuppressWarnings("unchecked")
+ 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), (DBusSigHandler<? extends DBusSignal>) handler);
+ }
+
+ protected abstract <T extends DBusSignal> void addSigHandler(DBusMatchRule rule, DBusSigHandler<T> handler) throws DBusException;
+
+ // pego was protedted, made public
+ public <T extends DBusSignal> void addSigHandlerWithoutMatch(Class<? extends DBusSignal> signal, DBusSigHandler<T> handler) throws DBusException
+ {
+ DBusMatchRule rule = new DBusMatchRule(signal);
+ SignalTuple key = new SignalTuple(rule.getInterface(), rule.getMember(), rule.getObject(), rule.getSource());
+ synchronized (handledSignals) {
+ Vector<DBusSigHandler<? extends DBusSignal>> v = handledSignals.get(key);
+ if (null == v) {
+ v = new Vector<DBusSigHandler<? extends DBusSignal>>();
+ v.add(handler);
+ handledSignals.put(key, v);
+ } else
+ v.add(handler);
+ }
+ }
+
+ /**
+ * Disconnect from the Bus.
+ */
+ public void disconnect()
+ {
+ connected = false;
+ if (Debug.debug) Debug.print(Debug.INFO, "Sending disconnected signal");
+ try {
+ handleMessage(new org.freedesktop.DBus.Local.Disconnected("/"));
+ } catch (Exception ee) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, ee);
+ }
+
+ if (Debug.debug) Debug.print(Debug.INFO, "Disconnecting Abstract Connection");
+ // run all pending tasks.
+ while (runnables.size() > 0)
+ synchronized (runnables) {
+ runnables.notifyAll();
+ }
+
+ // stop the main thread
+ _run = false;
+
+ // unblock the sending thread.
+ synchronized (outgoing) {
+ outgoing.notifyAll();
+ }
+
+ // disconnect from the trasport layer
+ try {
+ if (null != transport) {
+ transport.disconnect();
+ transport = null;
+ }
+ } 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 set a callback.
+ * This handler will be called in a separate thread.
+ * @param object The remote object on which to call the method.
+ * @param m The name of the method on the interface to call.
+ * @param callback The callback handler.
+ * @param parameters The parameters to call the method with.
+ */
+ @SuppressWarnings("unchecked")
+ public <A> void callWithCallback(DBusInterface object, String m, CallbackHandler<A> callback, Object... parameters)
+ {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "callWithCallback("+object+","+m+", "+callback);
+ 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 = null;
+ if (null == ro.iface)
+ me = object.getClass().getMethod(m, types);
+ else {
+ Method[] methods = ro.iface.getMethods();
+ for (Method method: methods) {
+// System.out.println(method.getName());
+ for (Class<?> parameterType: method.getParameterTypes()) {
+// System.out.println("parameter: " + parameterType.getName());
+ }
+ if (method.getName().equals(m)) {
+ me = method;
+ }
+ }
+// Following code doesn't work: if actual paremeter is BasicEList and definition of parameter is List, the method is not found
+// try {
+// Method me2 = ro.iface.getMethod(m, types);
+// } catch (NoSuchMethodException e) {
+// System.out.println("NoSuchMethodException: method name = " + m);
+// for (Class type: types) {
+// System.out.println("type = " + type.getName());
+// }
+// }
+ }
+ RemoteInvocationHandler.executeRemoteMethod(ro, me, this, RemoteInvocationHandler.CALL_TYPE_CALLBACK, callback, parameters);
+ } catch (DBusExecutionException DBEe) {
+ DBEe.printStackTrace();
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
+ throw DBEe;
+ } catch (Exception e) {
+ e.printStackTrace();
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ throw new DBusExecutionException(e.getMessage());
+ }
+ }
+
+ /**
+ * 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.
+ */
+ @SuppressWarnings("unchecked")
+ 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 = null;
+ if (null == ro.iface) {
+// System.out.println("ro.iface == null");
+ me = object.getClass().getMethod(m, types);
+ } else {
+// System.out.println("ro.iface != null");
+ Method[] methods = ro.iface.getMethods();
+ for (Method method: methods) {
+// System.out.println(method.getName());
+// for (Class<?> parameterType: method.getParameterTypes()) {
+// System.out.println("parameter: " + parameterType.getName());
+// }
+ if (method.getName().equals(m)) {
+ me = method;
+ }
+ }
+// me = ro.iface.getMethod(m, types);
+// System.out.println("me = " + me);
+ }
+ return (DBusAsyncReply) RemoteInvocationHandler.executeRemoteMethod(ro, me, this, RemoteInvocationHandler.CALL_TYPE_ASYNC, null, parameters);
+ } catch (DBusExecutionException DBEe) {
+ DBEe.printStackTrace();
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
+ throw DBEe;
+ } catch (Exception e) {
+ e.printStackTrace();
+ 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.DEBUG, "Handling incoming method call: "+m);
+
+ currentSender = m.getSource(); // pego
+ ExportedObject eo = null;
+ Method meth = null;
+ Object o = null;
+
+ if (null == m.getInterface() ||
+ m.getInterface().equals("org.freedesktop.DBus.Peer") ||
+ m.getInterface().equals("org.freedesktop.DBus.Introspectable")) {
+ synchronized (exportedObjects) {
+ eo = exportedObjects.get(null);
+ }
+ if (null != eo && null == eo.object.get()) {
+ unExportObject(null);
+ eo = null;
+ }
+ if (null != eo) {
+ meth = eo.methods.get(new MethodTuple(m.getName(), m.getSig()));
+ }
+ if (null != meth)
+ o = new _globalhandler(m.getPath());
+ else
+ eo = null;
+ }
+ if (null == o) {
+ // now check for specific exported functions
+
+ synchronized (exportedObjects) {
+ eo = exportedObjects.get(m.getPath());
+ }
+ if (null != eo && null == eo.object.get()) {
+ if (Debug.debug) Debug.print(Debug.INFO, "Unexporting "+m.getPath()+" implicitly");
+ unExportObject(m.getPath());
+ eo = null;
+ }
+
+ if (null == eo) {
+ eo = fallbackcontainer.get(m.getPath());
+ }
+
+ if (null == eo) {
+ try {
+ queueOutgoing(new Error(m, new DBus.Error.UnknownObject(m.getPath()+_(" is not an object provided by this process."))));
+ } catch (DBusException DBe) {}
+ return;
+ }
+ if (Debug.debug) {
+ Debug.print(Debug.VERBOSE, "Searching for method "+m.getName()+" with signature "+m.getSig());
+ Debug.print(Debug.VERBOSE, "List of methods on "+eo+":");
+ for (MethodTuple mt: eo.methods.keySet())
+ Debug.print(Debug.VERBOSE, " "+mt+" => "+eo.methods.get(mt));
+ }
+ meth = eo.methods.get(new MethodTuple(m.getName(), m.getSig()));
+ if (null == meth) {
+ try {
+ queueOutgoing(new Error(m, new DBus.Error.UnknownMethod(MessageFormat.format(_("The method `{0}.{1}' does not exist on this object."), new Object[] { m.getInterface(), m.getName() }))));
+ } catch (DBusException DBe) {}
+ return;
+ }
+ o = eo.object.get();
+ }
+
+ // now execute it
+ final Method me = meth;
+ final Object ob = o;
+ final boolean noreply = (1 == (m.getFlags() & Message.Flags.NO_REPLY_EXPECTED));
+ final DBusCallInfo info = new DBusCallInfo(m);
+ final AbstractConnection conn = this;
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Adding Runnable for method "+meth);
+ addRunnable(new Runnable()
+ {
+ private boolean run = false;
+ public synchronized void run()
+ {
+ if (run) return;
+ run = true;
+ 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) {
+ e.printStackTrace();
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ try {
+ conn.queueOutgoing(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 {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Invoking Method: "+me+" on "+ob+" with parameters "+Arrays.deepToString(m.getParameters()));
+ result = me.invoke(ob, m.getParameters());
+ } catch (InvocationTargetException ITe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, ITe.getCause());
+ 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);
+ }
+ conn.queueOutgoing(reply);
+ }
+ } catch (DBusExecutionException DBEe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBEe);
+ try {
+ conn.queueOutgoing(new Error(m, DBEe));
+ } catch (DBusException DBe) {}
+ } catch (Throwable e) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ try {
+ conn.queueOutgoing(new Error(m, new DBusExecutionException(MessageFormat.format(_("Error Executing Method {0}.{1}: {2}"), new Object[] { m.getInterface(), m.getName(), e.getMessage() }))));
+ } catch (DBusException DBe) {}
+ }
+ }
+ });
+ }
+ @SuppressWarnings({"unchecked","deprecation"})
+ private void handleMessage(final DBusSignal s)
+ {
+ if (Debug.debug) Debug.print(Debug.DEBUG, "Handling incoming signal: "+s);
+ Vector<DBusSigHandler<? extends DBusSignal>> v = new Vector<DBusSigHandler<? extends DBusSignal>>();
+ synchronized(handledSignals) {
+ Vector<DBusSigHandler<? extends DBusSignal>> 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 AbstractConnection conn = this;
+ for (final DBusSigHandler<? extends DBusSignal> h: v) {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Adding Runnable for signal "+s+" with handler "+h);
+ addRunnable(new Runnable() {
+ private boolean run = false;
+ public synchronized void run()
+ {
+ if (run) return;
+ run = true;
+ try {
+ DBusSignal rs;
+ if (s instanceof DBusSignal.internalsig || s.getClass().equals(DBusSignal.class))
+ rs = s.createReal(conn);
+ else
+ rs = s;
+ ((DBusSigHandler<DBusSignal>)h).handle(rs);
+ } catch (DBusException DBe) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, DBe);
+ try {
+ conn.queueOutgoing(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.DEBUG, "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);
+ CallbackHandler cbh = null;
+ DBusAsyncReply asr = null;
+ synchronized (pendingCallbacks) {
+ cbh = pendingCallbacks.remove(m);
+ if (Debug.debug) Debug.print(Debug.VERBOSE, cbh+" = pendingCallbacks.remove("+m+")");
+ asr = pendingCallbackReplys.remove(m);
+ }
+ // queue callback for execution
+ if (null != cbh) {
+ final CallbackHandler fcbh = cbh;
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Adding Error Runnable with callback handler "+fcbh);
+ addRunnable(new Runnable() {
+ private boolean run = false;
+ public synchronized void run()
+ {
+ if (run) return;
+ run = true;
+ try {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Running Error Callback for "+err);
+ DBusCallInfo info = new DBusCallInfo(err);
+ synchronized (infomap) {
+ infomap.put(Thread.currentThread(), info);
+ }
+
+ fcbh.handleError(err.getException());
+ synchronized (infomap) {
+ infomap.remove(Thread.currentThread());
+ }
+
+ } catch (Exception e) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ }
+ }
+ });
+ }
+
+ }
+ else
+ synchronized (pendingErrors) {
+ pendingErrors.addLast(err); }
+ }
+ @SuppressWarnings("unchecked")
+ private void handleMessage(final MethodReturn mr)
+ {
+ if (Debug.debug) Debug.print(Debug.DEBUG, "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);
+ CallbackHandler cbh = null;
+ DBusAsyncReply asr = null;
+ synchronized (pendingCallbacks) {
+ cbh = pendingCallbacks.remove(m);
+ if (Debug.debug) Debug.print(Debug.VERBOSE, cbh+" = pendingCallbacks.remove("+m+")");
+ asr = pendingCallbackReplys.remove(m);
+ }
+ // queue callback for execution
+ if (null != cbh) {
+ final CallbackHandler fcbh = cbh;
+ final DBusAsyncReply fasr = asr;
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Adding Runnable for method "+fasr.getMethod()+" with callback handler "+fcbh);
+ addRunnable(new Runnable() {
+ private boolean run = false;
+ public synchronized void run()
+ {
+ if (run) return;
+ run = true;
+ try {
+ if (Debug.debug) Debug.print(Debug.VERBOSE, "Running Callback for "+mr);
+ DBusCallInfo info = new DBusCallInfo(mr);
+ synchronized (infomap) {
+ infomap.put(Thread.currentThread(), info);
+ }
+
+ fcbh.handle(RemoteInvocationHandler.convertRV(mr.getSig(), mr.getParameters(), fasr.getMethod(), fasr.getConnection()));
+ synchronized (infomap) {
+ infomap.remove(Thread.currentThread());
+ }
+
+ } catch (Exception e) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ }
+ }
+ });
+ }
+
+ } else
+ try {
+ queueOutgoing(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 (!connected) throw new NotConnected(_("Disconnected"));
+ if (m instanceof DBusSignal)
+ ((DBusSignal) m).appendbody(this);
+
+ 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);
+ }
+ }
+
+ transport.mout.writeMessage(m);
+
+ } catch (Exception e) {
+ if (EXCEPTION_DEBUG && Debug.debug) Debug.print(Debug.ERR, e);
+ if (m instanceof MethodCall && e instanceof NotConnected)
+ try {
+ ((MethodCall) m).setReply(new Error("org.freedesktop.DBus.Local", "org.freedesktop.DBus.Local.Disconnected", 0, "s", new Object[] { _("Disconnected") }));
+ } catch (DBusException DBe) {}
+ 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);
+ }
+ if (e instanceof IOException) disconnect();
+ }
+ }
+ private Message readIncoming() throws DBusException
+ {
+ if (!connected) throw new NotConnected(_("No transport present"));
+ 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() throws ParseException { return new BusAddress(addr); }
+}