All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.freedesktop.dbus.connections.impl.DirectConnection Maven / Gradle / Ivy

Go to download

Slightly improved version of the Java DBus library provided by freedesktop.org (https://dbus.freedesktop.org/doc/dbus-java/). Changes: - Fixed lot's of Java warnings - Fixed broken 'Gettext' feature (Exceptions on unsupported languages, usage of "_" as method name). - Renamed some classes/methods/variables to comply with Java naming scheme. - Removed usage of proprietary logger and replaced it with sl4fj. - Renamed/refactored some parts to be more 'Java' like (e.g. naming, shadowing) - Fixed problems with DbusConnection.getConnection(SESSION) when using display export (e.g. SSH X11 forward)

There is a newer version: 3.3.2
Show newest version
/*
   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.connections.impl;

import java.io.File;
import java.lang.reflect.Proxy;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.freedesktop.Hexdump;
import org.freedesktop.dbus.DBusMatchRule;
import org.freedesktop.dbus.RemoteInvocationHandler;
import org.freedesktop.dbus.RemoteObject;
import org.freedesktop.dbus.SignalTuple;
import org.freedesktop.dbus.connections.AbstractConnection;
import org.freedesktop.dbus.connections.Transport;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.interfaces.DBusInterface;
import org.freedesktop.dbus.interfaces.DBusSigHandler;
import org.freedesktop.dbus.interfaces.Introspectable;
import org.freedesktop.dbus.messages.DBusSignal;
import org.freedesktop.dbus.messages.ExportedObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.hypfvieh.util.StringUtil;

/** Handles a peer to peer connection between two applications withou a bus daemon.
 * 

* Signal Handlers and method calls from remote objects are run in their own threads, you MUST handle the concurrency issues. *

*/ public class DirectConnection extends AbstractConnection { private final Logger logger = LoggerFactory.getLogger(getClass()); private final String machineId; /** * 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. * @throws DBusException on error */ public DirectConnection(String address) throws DBusException { super(address); machineId = createMachineId(); if (!getAddress().isServer()) { super.listen(); } } /** * Use this method when running on server side. * Call will block. */ @Override public void listen() { if (getAddress().isServer()) { super.listen(); } } private String createMachineId() { String ascii; try { ascii = Hexdump.toAscii(MessageDigest.getInstance("MD5").digest(InetAddress.getLocalHost().getHostName().getBytes())); return ascii; } catch (NoSuchAlgorithmException | UnknownHostException _ex) { } return StringUtil.randomString(32); } /** * Creates a bus address for a randomly generated tcp port. * @return a random bus address. */ public static String createDynamicTCPSession() { String address = "tcp:host=localhost"; int port; try { ServerSocket s = new ServerSocket(); s.bind(null); port = s.getLocalPort(); s.close(); } catch (Exception e) { Random r = new Random(); port = 32768 + (Math.abs(r.nextInt()) % 28232); } address += ",port=" + port; address += ",guid=" + Transport.genGUID(); LoggerFactory.getLogger(DirectConnection.class).debug("Created Session address: {}", address); return address; } /** * Creates a bus address for a randomly generated abstract unix socket. * @return a random bus address. */ public static String createDynamicSession() { String address = "unix:"; 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()); LoggerFactory.getLogger(DirectConnection.class).trace("Trying path {}", path); } while ((new File(path)).exists()); address += "abstract=" + path; address += ",guid=" + Transport.genGUID(); LoggerFactory.getLogger(DirectConnection.class).debug("Created Session address: {}", address); return address; } DBusInterface dynamicProxy(String path) throws DBusException { try { Introspectable intro = getRemoteObject(path, Introspectable.class); String data = intro.Introspect(); String[] tags = data.split("[<>]"); List ifaces = new ArrayList<>(); for (String tag : tags) { if (tag.startsWith("interface")) { ifaces.add(tag.replaceAll("^interface *name *= *['\"]([^'\"]*)['\"].*$", "$1")); } } List> ifcs = new ArrayList<>(); 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(), ifcs.toArray(new Class[0]), new RemoteInvocationHandler(this, ro)); getImportedObjects().put(newi, ro); return newi; } catch (Exception e) { logger.debug("", e); throw new DBusException(String.format("Failed to create proxy object for %s; reason: %s.", path, e.getMessage())); } } DBusInterface getExportedObject(String path) throws DBusException { ExportedObject o = null; synchronized (getExportedObjects()) { o = getExportedObjects().get(path); } if (null != o && null == o.getObject().get()) { unExportObject(path); o = null; } if (null != o) { return o.getObject().get(); } 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 * may block and may fail. 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. * @param class which extends DBusInterface * @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 T getRemoteObject(String objectpath, Class 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); @SuppressWarnings("unchecked") T i = (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, new RemoteInvocationHandler(this, ro)); getImportedObjects().put(i, ro); return i; } @Override protected void removeSigHandler(DBusMatchRule rule, DBusSigHandler handler) throws DBusException { SignalTuple key = new SignalTuple(rule.getInterface(), rule.getMember(), rule.getObject(), rule.getSource()); synchronized (getHandledSignals()) { List> v = getHandledSignals().get(key); if (null != v) { v.remove(handler); if (0 == v.size()) { getHandledSignals().remove(key); } } } } @Override protected void addSigHandler(DBusMatchRule rule, DBusSigHandler handler) throws DBusException { SignalTuple key = new SignalTuple(rule.getInterface(), rule.getMember(), rule.getObject(), rule.getSource()); synchronized (getHandledSignals()) { List> v = getHandledSignals().get(key); if (null == v) { v = new ArrayList<>(); v.add(handler); getHandledSignals().put(key, v); } else { v.add(handler); } } } @Override public DBusInterface getExportedObject(String source, String path) throws DBusException { return getExportedObject(path); } @Override public String getMachineId() { return machineId; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy