Package com.lucimber.dbus.standard
This package provides Java implementations of standard D-Bus interfaces that are commonly used across different D-Bus applications. These interfaces follow the official D-Bus specification and provide type-safe access to standard D-Bus functionality.
Getting Started
For first-time users: Start with Introspectable
to discover available
interfaces and methods, then use Properties
for property access. The Peer
interface provides connectivity testing, while ObjectManager
enables efficient object
hierarchy discovery. Most D-Bus interactions use custom interfaces specific to each service.
Standard Interfaces
Introspection Interface
The org.freedesktop.DBus.Introspectable
interface allows clients to discover the
structure and capabilities of D-Bus objects:
// Introspect a D-Bus object
OutboundMethodCall introspectCall = OutboundMethodCall.Builder
.create()
.withPath(DBusObjectPath.valueOf("/org/example/Object"))
.withInterface(DBusString.valueOf("org.freedesktop.DBus.Introspectable"))
.withMember(DBusString.valueOf("Introspect"))
.withDestination(DBusString.valueOf("org.example.Service"))
.withReplyExpected(true)
.build();
CompletableFuture<InboundMessage> response = connection.sendRequest(introspectCall);
response.thenAccept(reply -> {
if (reply instanceof InboundMethodReturn) {
InboundMethodReturn returnMsg = (InboundMethodReturn) reply;
List<DBusType> body = returnMsg.getBody();
if (!body.isEmpty()) {
DBusString xmlData = (DBusString) body.get(0);
System.out.println("Introspection XML: " + xmlData.toString());
}
}
});
Properties Interface
The org.freedesktop.DBus.Properties
interface provides standardized property access
for D-Bus objects:
// Get a property value
OutboundMethodCall getProperty = OutboundMethodCall.Builder
.create()
.withPath(DBusObjectPath.valueOf("/org/example/Object"))
.withInterface(DBusString.valueOf("org.freedesktop.DBus.Properties"))
.withMember(DBusString.valueOf("Get"))
.withDestination(DBusString.valueOf("org.example.Service"))
.withBody(Arrays.asList(
DBusString.valueOf("org.example.Interface"),
DBusString.valueOf("PropertyName")
))
.withReplyExpected(true)
.build();
// Set a property value
OutboundMethodCall setProperty = OutboundMethodCall.Builder
.create()
.withPath(DBusObjectPath.valueOf("/org/example/Object"))
.withInterface(DBusString.valueOf("org.freedesktop.DBus.Properties"))
.withMember(DBusString.valueOf("Set"))
.withDestination(DBusString.valueOf("org.example.Service"))
.withBody(Arrays.asList(
DBusString.valueOf("org.example.Interface"),
DBusString.valueOf("PropertyName"),
DBusVariant.valueOf(DBusString.valueOf("NewValue"))
))
.withReplyExpected(true)
.build();
// Get all properties
OutboundMethodCall getAllProperties = OutboundMethodCall.Builder
.create()
.withPath(DBusObjectPath.valueOf("/org/example/Object"))
.withInterface(DBusString.valueOf("org.freedesktop.DBus.Properties"))
.withMember(DBusString.valueOf("GetAll"))
.withDestination(DBusString.valueOf("org.example.Service"))
.withBody(Arrays.asList(
DBusString.valueOf("org.example.Interface")
))
.withReplyExpected(true)
.build();
Peer Interface
The org.freedesktop.DBus.Peer
interface provides basic peer-to-peer functionality for
D-Bus connections:
// Ping a D-Bus peer
OutboundMethodCall ping = OutboundMethodCall.Builder
.create()
.withPath(DBusObjectPath.valueOf("/"))
.withInterface(DBusString.valueOf("org.freedesktop.DBus.Peer"))
.withMember(DBusString.valueOf("Ping"))
.withDestination(DBusString.valueOf("org.example.Service"))
.withReplyExpected(true)
.build();
// Get machine UUID
OutboundMethodCall getMachineId = OutboundMethodCall.Builder
.create()
.withPath(DBusObjectPath.valueOf("/"))
.withInterface(DBusString.valueOf("org.freedesktop.DBus.Peer"))
.withMember(DBusString.valueOf("GetMachineId"))
.withDestination(DBusString.valueOf("org.example.Service"))
.withReplyExpected(true)
.build();
ObjectManager Interface
The org.freedesktop.DBus.ObjectManager
interface provides efficient enumeration of
object hierarchies:
// Get all managed objects
OutboundMethodCall getManagedObjects = OutboundMethodCall.Builder
.create()
.withPath(DBusObjectPath.valueOf("/org/example"))
.withInterface(DBusString.valueOf("org.freedesktop.DBus.ObjectManager"))
.withMember(DBusString.valueOf("GetManagedObjects"))
.withDestination(DBusString.valueOf("org.example.Service"))
.withReplyExpected(true)
.build();
CompletableFuture<InboundMessage> response = connection.sendRequest(getManagedObjects);
response.thenAccept(reply -> {
if (reply instanceof InboundMethodReturn) {
InboundMethodReturn returnMsg = (InboundMethodReturn) reply;
List<DBusType> body = returnMsg.getBody();
if (!body.isEmpty()) {
DBusDict<DBusObjectPath, DBusDict<DBusString, DBusDict<DBusString, DBusVariant>>>
managedObjects = (DBusDict) body.get(0);
managedObjects.forEach((path, interfaces) -> {
System.out.println("Object: " + path);
interfaces.forEach((iface, properties) -> {
System.out.println(" Interface: " + iface);
properties.forEach((prop, value) -> {
System.out.println(" " + prop + " = " + value);
});
});
});
}
}
});
Bus Interface
The org.freedesktop.DBus
interface provides access to the D-Bus daemon functionality:
// List available services
OutboundMethodCall listNames = OutboundMethodCall.Builder
.create()
.withPath(DBusObjectPath.valueOf("/org/freedesktop/DBus"))
.withInterface(DBusString.valueOf("org.freedesktop.DBus"))
.withMember(DBusString.valueOf("ListNames"))
.withDestination(DBusString.valueOf("org.freedesktop.DBus"))
.withReplyExpected(true)
.build();
// Request a service name
OutboundMethodCall requestName = OutboundMethodCall.Builder
.create()
.withPath(DBusObjectPath.valueOf("/org/freedesktop/DBus"))
.withInterface(DBusString.valueOf("org.freedesktop.DBus"))
.withMember(DBusString.valueOf("RequestName"))
.withDestination(DBusString.valueOf("org.freedesktop.DBus"))
.withBody(Arrays.asList(
DBusString.valueOf("org.example.MyService"),
DBusUInt32.valueOf(0) // No flags
))
.withReplyExpected(true)
.build();
// Get service owner
OutboundMethodCall getNameOwner = OutboundMethodCall.Builder
.create()
.withPath(DBusObjectPath.valueOf("/org/freedesktop/DBus"))
.withInterface(DBusString.valueOf("org.freedesktop.DBus"))
.withMember(DBusString.valueOf("GetNameOwner"))
.withDestination(DBusString.valueOf("org.freedesktop.DBus"))
.withBody(Arrays.asList(
DBusString.valueOf("org.example.Service")
))
.withReplyExpected(true)
.build();
Signal Handling
Standard interfaces also define common signals:
// Handle PropertiesChanged signals
connection.getPipeline().addLast("properties-handler", new AbstractInboundHandler() {
@Override
public void handleInboundMessage(Context ctx, InboundMessage msg) {
if (msg instanceof InboundSignal) {
InboundSignal signal = (InboundSignal) msg;
String interfaceName = signal.getInterfaceName()
.map(DBusString::toString)
.orElse("");
String memberName = signal.getMember().toString();
if ("org.freedesktop.DBus.Properties".equals(interfaceName) &&
"PropertiesChanged".equals(memberName)) {
handlePropertiesChanged(signal);
}
}
ctx.propagateInboundMessage(msg);
}
private void handlePropertiesChanged(InboundSignal signal) {
List<DBusType> arguments = signal.getBody();
if (arguments.size() >= 2) {
DBusString interfaceName = (DBusString) arguments.get(0);
DBusDict<DBusString, DBusVariant> changedProperties =
(DBusDict<DBusString, DBusVariant>) arguments.get(1);
System.out.println("Properties changed on " + interfaceName);
changedProperties.forEach((key, value) -> {
System.out.println(" " + key + " = " + value);
});
}
}
});
// Handle NameOwnerChanged signals
connection.getPipeline().addLast("name-owner-handler", new AbstractInboundHandler() {
@Override
public void handleInboundMessage(Context ctx, InboundMessage msg) {
if (msg instanceof InboundSignal) {
InboundSignal signal = (InboundSignal) msg;
String interfaceName = signal.getInterfaceName()
.map(DBusString::toString)
.orElse("");
String memberName = signal.getMember().toString();
if ("org.freedesktop.DBus".equals(interfaceName) &&
"NameOwnerChanged".equals(memberName)) {
handleNameOwnerChanged(signal);
}
}
ctx.propagateInboundMessage(msg);
}
private void handleNameOwnerChanged(InboundSignal signal) {
List<DBusType> arguments = signal.getBody();
if (arguments.size() >= 3) {
String serviceName = ((DBusString) arguments.get(0)).toString();
String oldOwner = ((DBusString) arguments.get(1)).toString();
String newOwner = ((DBusString) arguments.get(2)).toString();
if (oldOwner.isEmpty() && !newOwner.isEmpty()) {
System.out.println("Service appeared: " + serviceName);
} else if (!oldOwner.isEmpty() && newOwner.isEmpty()) {
System.out.println("Service disappeared: " + serviceName);
}
}
}
});
// Handle ObjectManager InterfacesAdded/Removed signals
connection.getPipeline().addLast("object-manager-handler", new AbstractInboundHandler() {
@Override
public void handleInboundMessage(Context ctx, InboundMessage msg) {
if (msg instanceof InboundSignal) {
InboundSignal signal = (InboundSignal) msg;
String interfaceName = signal.getInterfaceName()
.map(DBusString::toString)
.orElse("");
String memberName = signal.getMember().toString();
if ("org.freedesktop.DBus.ObjectManager".equals(interfaceName)) {
if ("InterfacesAdded".equals(memberName)) {
handleInterfacesAdded(signal);
} else if ("InterfacesRemoved".equals(memberName)) {
handleInterfacesRemoved(signal);
}
}
}
ctx.propagateInboundMessage(msg);
}
private void handleInterfacesAdded(InboundSignal signal) {
List<DBusType> arguments = signal.getBody();
if (arguments.size() >= 2) {
DBusObjectPath objectPath = (DBusObjectPath) arguments.get(0);
DBusDict<DBusString, DBusDict<DBusString, DBusVariant>> interfaces =
(DBusDict) arguments.get(1);
System.out.println("Interfaces added to " + objectPath);
interfaces.forEach((iface, properties) -> {
System.out.println(" Interface: " + iface);
});
}
}
private void handleInterfacesRemoved(InboundSignal signal) {
List<DBusType> arguments = signal.getBody();
if (arguments.size() >= 2) {
DBusObjectPath objectPath = (DBusObjectPath) arguments.get(0);
DBusArray<DBusString> interfaces = (DBusArray) arguments.get(1);
System.out.println("Interfaces removed from " + objectPath);
interfaces.forEach(iface -> {
System.out.println(" Interface: " + iface);
});
}
}
});
Error Handling
Standard D-Bus error names are defined for common error conditions:
// Handle standard D-Bus errors
private void handleStandardErrors(InboundError error) {
String errorName = error.getErrorName().toString();
switch (errorName) {
case "org.freedesktop.DBus.Error.ServiceUnknown":
System.err.println("Service not found");
break;
case "org.freedesktop.DBus.Error.UnknownMethod":
System.err.println("Method not found");
break;
case "org.freedesktop.DBus.Error.UnknownInterface":
System.err.println("Interface not found");
break;
case "org.freedesktop.DBus.Error.UnknownObject":
System.err.println("Object not found");
break;
case "org.freedesktop.DBus.Error.InvalidArgs":
System.err.println("Invalid arguments");
break;
case "org.freedesktop.DBus.Error.AccessDenied":
System.err.println("Access denied");
break;
case "org.freedesktop.DBus.Error.NoReply":
System.err.println("No reply received");
break;
default:
System.err.println("D-Bus error: " + errorName);
}
}
Utility Classes
Helper classes for working with standard interfaces:
// Standard interface constants
public static final String INTROSPECTABLE_INTERFACE = "org.freedesktop.DBus.Introspectable";
public static final String PROPERTIES_INTERFACE = "org.freedesktop.DBus.Properties";
public static final String PEER_INTERFACE = "org.freedesktop.DBus.Peer";
public static final String OBJECT_MANAGER_INTERFACE = "org.freedesktop.DBus.ObjectManager";
public static final String DBUS_INTERFACE = "org.freedesktop.DBus";
// Helper methods for common operations
public static CompletableFuture<String> introspectObject(Connection connection,
String serviceName,
String objectPath) {
// Implementation for introspection
}
public static CompletableFuture<DBusVariant> getProperty(Connection connection,
String serviceName,
String objectPath,
String interfaceName,
String propertyName) {
// Implementation for property access
}
Best Practices
- Use Standard Interfaces: Always use these standard interfaces when available
- Error Handling: Handle standard D-Bus errors appropriately
- Property Changes: Subscribe to PropertiesChanged signals for reactive updates
- Service Discovery: Use introspection to discover available interfaces and methods
- Peer Communication: Use Peer interface for basic connectivity testing
Compatibility
All standard interfaces in this package are compatible with:
- D-Bus specification version 1.0 and later
- Common D-Bus implementations (dbus-daemon, systemd, etc.)
- Cross-platform D-Bus services
- Both system and session bus environments
- Since:
- 1.0
- See Also:
-
InterfacesClassDescriptionThe org.freedesktop.DBus.Introspectable interface provides introspection data for D-Bus objects.The org.freedesktop.DBus.ObjectManager interface provides a standardized way to enumerate all objects below a certain path in the object hierarchy, along with their interfaces and properties.The org.freedesktop.DBus.Peer interface provides basic peer-to-peer functionality between D-Bus connections.The org.freedesktop.DBus.Properties interface provides methods to expose properties or attributes of objects.