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

org.freedesktop.dbus.bin.EmbeddedDBusDaemon Maven / Gradle / Ivy

Go to download

Improved version of the DBus-Java library provided by freedesktop.org (https://dbus.freedesktop.org/doc/dbus-java/).

There is a newer version: 5.1.0
Show newest version
package org.freedesktop.dbus.bin;

import org.freedesktop.dbus.connections.BusAddress;
import org.freedesktop.dbus.connections.transports.AbstractTransport;
import org.freedesktop.dbus.connections.transports.TransportBuilder;
import org.freedesktop.dbus.connections.transports.TransportBuilder.SaslAuthMode;
import org.freedesktop.dbus.connections.transports.TransportConnection;
import org.freedesktop.dbus.exceptions.AuthenticationException;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.exceptions.SocketClosedException;
import org.freedesktop.dbus.utils.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.IOException;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Simple DBusDaemon implementation to use if no DBusDaemon is running on the OS level.
 */
public class EmbeddedDBusDaemon implements Closeable {

    private static final Logger LOGGER = LoggerFactory.getLogger(EmbeddedDBusDaemon.class);

    private final BusAddress address;

    private DBusDaemon daemon;

    private final AtomicBoolean closed = new AtomicBoolean(false);
    private final AtomicBoolean connectionReady = new AtomicBoolean(false);

    private SaslAuthMode saslAuthMode;

    private String unixSocketFileOwner;

    private String unixSocketFileGroup;

    private PosixFilePermission[] unixSocketFilePermissions;

    public EmbeddedDBusDaemon(BusAddress _address) {
        // create copy of address so manipulation happens later does not interfere with our instance
        address = BusAddress.of(Objects.requireNonNull(_address, "Address required"));
    }

    public EmbeddedDBusDaemon(String _address) throws DBusException {
        this(BusAddress.of(_address));
    }

    /**
     * Shutdown the running DBusDaemon instance.
     */
    @Override
    public synchronized void close() throws IOException {
        closed.set(true);
        connectionReady.set(false);
        if (daemon != null) {
            daemon.close();
            try {
                daemon.join(5000L);
            } catch (InterruptedException _ex) {
                LOGGER.debug("Interrupted while waiting for daemon thread to terminate");
            }
            daemon = null;
        }
    }

    /**
     * Run the DBusDaemon in foreground.
     * 

* This is a blocking operation. */ public void startInForeground() { try { startListening(); } catch (IOException | DBusException _ex) { if (!closed.get()) { throw new RuntimeException(_ex); } } } /** * Start the DBusDaemon in background and returns immediately. *

* This method may return before the background thread is ready. * To ensure the the background thread is running on return use {@link #startInBackgroundAndWait(long)}. */ public void startInBackground() { Thread thread = new Thread(this::startInForeground); String threadName = address.toString().replaceAll("^([^,]+),.+", "$1"); thread.setName("EmbeddedDBusDaemon-" + threadName); thread.setDaemon(true); thread.setUncaughtExceptionHandler((th, ex) -> LOGGER.error("Got uncaught exception", ex)); thread.start(); } /** * Starts the DBusDaemon in background. *

* Will wait up to the given period of milliseconds for the background thread to get ready. * If given wait time exceeded, a {@link RuntimeException} is thrown. * * @param _maxWaitMillis maximum wait time in milliseconds */ public void startInBackgroundAndWait(long _maxWaitMillis) { startInBackground(); Util.waitFor("EmbeddedDbusDaemon", this::isRunning, _maxWaitMillis, 100); } /** * Whether the DBusDaemon is still running. * * @return true if running, false otherwise */ public synchronized boolean isRunning() { return connectionReady.get() && daemon != null && daemon.isRunning(); } /** * The currently configured {@link SaslAuthMode}. * When null is returned, the {@link SaslAuthMode} of the transport provider is used. * * @return {@link SaslAuthMode} or null */ public SaslAuthMode getSaslAuthMode() { return saslAuthMode; } /** * Use this to override the default authentication mode which would * be used by the transport based on the {@link BusAddress}. * * @param _saslAuthMode auth mode, null to use default */ public void setSaslAuthMode(SaslAuthMode _saslAuthMode) { saslAuthMode = _saslAuthMode; } /** * The file owner for the created unix socket.
* Ignored if TCP is used.
*
* Will only work if currently running JVM process user * has suitable permissions to change the owner. * * @param _owner owner to set */ public void setUnixSocketOwner(String _owner) { unixSocketFileOwner = _owner; } /** * The file group for the created unix socket.
* Ignored if TCP is used.
*
* Will only work if currently running JVM process user * has suitable permissions to change the group. * * @param _group group to set */ public void setUnixSocketGroup(String _group) { unixSocketFileGroup = _group; } /** * The file permissions for the created unix socket.
* Ignored if TCP is used or if the OS is Windows.
*
* Will only work if currently running JVM process user * has suitable permissions to change the permissions. * * @param _permissions permissions to set */ public void setUnixSocketPermissions(PosixFilePermission... _permissions) { unixSocketFilePermissions = _permissions; } private synchronized void setDaemonAndStart(AbstractTransport _transport) { daemon = new DBusDaemon(_transport); daemon.start(); } /** * Start listening for incoming connections. *

* Will throw {@link IllegalArgumentException} if a unsupported transport is used. * * @throws IOException when connection fails * @throws DBusException when the provided bus address is wrong */ private void startListening() throws IOException, DBusException { if (!TransportBuilder.getRegisteredBusTypes().contains(address.getBusType())) { throw new IllegalArgumentException("Unknown or unsupported address type: " + address.getType()); } LOGGER.debug("About to initialize transport on: {}", address); try (AbstractTransport transport = TransportBuilder.create(address).configure() .withUnixSocketFileOwner(unixSocketFileOwner) .withUnixSocketFileGroup(unixSocketFileGroup) .withUnixSocketFilePermissions(unixSocketFilePermissions) .withAutoConnect(false) .configureSasl().withAuthMode(getSaslAuthMode()).back() .back() .build()) { setDaemonAndStart(transport); // use tail-controlled loop so we at least try to get a client connection once do { try { LOGGER.debug("Begin listening to: {}", transport); connectionReady.set(true); TransportConnection s = transport.listen(); daemon.addSock(s); } catch (AuthenticationException _ex) { LOGGER.error("Authentication failed", _ex); } catch (SocketClosedException _ex) { LOGGER.debug("Connection closed", _ex); } } while (daemon.isRunning()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy