Skip to content

Commit

Permalink
Refactorings, Reduced duplicate code/documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
hypfvieh committed Nov 16, 2024
1 parent 09ba07e commit 39a57f3
Show file tree
Hide file tree
Showing 13 changed files with 464 additions and 204 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ The library will remain open source and MIT licensed and can still be used, fork
- Fixed issue with arrays, primitive arrays and `Collection` when used in signal constructors ([#268](https://github.com/hypfvieh/dbus-java/issues/268))
- Improvements when using library in Kotlin projects ([PR#270](https://github.com/hypfvieh/dbus-java/issues/270)), thanks to [vicr123](https://github.com/vicr123)
- Fixed exporting of methods which used a `Tuple` return type caused `ClassCastException` ([#271](https://github.com/hypfvieh/dbus-java/issues/271))
- Deprecated `ObjectPath`, use `DBusPath` instead
- Added `of(String...)` factory method to `DBusPath`
- Smaller refactorings to reduce duplicated code
- Added additional `getRemoteObject` methods which uses `DBusPath` as argument

##### Changes in 5.1.0 (2024-08-01):
- Use Junit BOM thanks to [spannm](https://github.com/spannm) ([PR#248](https://github.com/hypfvieh/dbus-java/issues/248))
Expand Down
46 changes: 41 additions & 5 deletions dbus-java-core/src/main/java/org/freedesktop/dbus/DBusPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,42 @@
import java.util.Objects;

public class DBusPath implements Comparable<DBusPath> {
private final String source;
private String path;

public DBusPath(String _source, String _path) {
source = _source;
path = _path;
}

public DBusPath(String _path) {
setPath(_path);
this(null, _path);
}

public String getPath() {
return path;
}

/**
* @deprecated path will be final in future, please do no longer use the setter.
*/
@Deprecated(forRemoval = true, since = "5.1.1 - 2024-11-16")
public void setPath(String _path) {
path = _path;
}

public String getSource() {
return source;
}

@Override
public String toString() {
return getPath();
}

@Override
public int hashCode() {
return Objects.hash(path);
return Objects.hash(source, path);
}

@Override
Expand All @@ -30,7 +48,11 @@ public boolean equals(Object _obj) {
} else if (_obj == null || getClass() != _obj.getClass()) {
return false;
}
return Objects.equals(path, ((DBusPath) _obj).path);

DBusPath dbusPath = (DBusPath) _obj;

return Objects.equals(path, dbusPath.path)
&& Objects.equals(source, dbusPath.source);
}

@Override
Expand All @@ -41,7 +63,21 @@ public int compareTo(DBusPath _that) {
return getPath().compareTo(_that.getPath());
}

public void setPath(String _path) {
path = _path;
/**
* Create a DBusPath object using one or multiple string parts.
* Leading slash will automatically appended if missing.
*
* @param _parts parts to build DBusPath
* @return DBusPath
* @throws IllegalArgumentException when no parts are given
*/
public static DBusPath of(String... _parts) {
if (_parts == null || _parts.length == 0) {
throw new IllegalArgumentException("No Strings given to build DBusPath");
}

String pathStr = _parts[0].indexOf('/') == 0 ? "" : "/" + String.join("/", _parts);

return new DBusPath(pathStr);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,15 @@ static Object deSerializeParameter(Object _parameter, Type _type, AbstractConnec
}
}

if (parameter instanceof DBusPath op) {
LOGGER.trace("Parameter is DBusPath");
if (_type instanceof Class && DBusInterface.class.isAssignableFrom((Class<?>) _type)) {
parameter = _conn.getExportedObject(op.getSource(), op.getPath(), (Class<DBusInterface>) _type);
} else {
parameter = new DBusPath(op.getPath());
}
}

// its an enum, parse either as the string name or the ordinal
if (parameter instanceof String str && _type instanceof Class && Enum.class.isAssignableFrom((Class<?>) _type)) {
LOGGER.trace("Type seems to be an enum");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import java.util.Objects;

/**
* @deprecated please use {@link DBusPath} instead
*/
@Deprecated(forRemoval = true, since = "5.1.1 - 2024-11-16")
public class ObjectPath extends DBusPath {
private String source;

Expand All @@ -10,6 +14,7 @@ public ObjectPath(String _source, String _path) {
this.source = _source;
}

@Override
public String getSource() {
return source;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
* issues.
* </p>
*/
public final class DBusConnection extends AbstractConnection {
public final class DBusConnection extends AbstractConnection implements IRemoteObjectGetter {

static final ConcurrentMap<String, DBusConnection> CONNECTIONS = new ConcurrentHashMap<>();

Expand Down Expand Up @@ -317,189 +317,34 @@ public String[] getNames() {
}).toArray(String[]::new);
}

public <I extends DBusInterface> I getPeerRemoteObject(String _busname, String _objectpath, Class<I> _type)
throws DBusException {
return getPeerRemoteObject(_busname, _objectpath, _type, true);
@Override
public String getDBusOwnerName(String _busName) {
return dbus == null ? null : dbus.GetNameOwner(_busName);
}

/**
* 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.
*
* 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 _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.$
* @return A reference to a remote object.
* @throws ClassCastException
* If type is not a sub-type of DBusInterface
* @throws InvalidBusNameException
* If busname or objectpath are incorrectly formatted.
* @throws DBusException
* If retrieving remote object fails
*/
@Override
public DBusInterface getPeerRemoteObject(String _busname, String _objectpath) throws InvalidBusNameException, DBusException {

DBusObjects.requireBusNameOrConnectionId(_busname);
String unique = dbus.GetNameOwner(_busname);

return dynamicProxy(unique, _objectpath, null);
return dynamicProxy(getDBusOwnerName(_busname), _objectpath, null);
}

/**
* 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 _busname
* The bus name to connect to. Usually a well known bus name 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.
* @return A reference to a remote object.
* @throws ClassCastException
* If type is not a sub-type of DBusInterface
* @throws DBusException
* If remote object cannot be retrieved
* @throws InvalidBusNameException
* If busname is incorrectly formatted
* @throws InvalidObjectPathException
* If objectpath is incorrectly formatted
*/
@Override
public DBusInterface getRemoteObject(String _busname, String _objectpath) throws DBusException, InvalidBusNameException, InvalidObjectPathException {
DBusObjects.requireBusNameOrConnectionId(_busname);
DBusObjects.requireObjectPath(_objectpath);

return dynamicProxy(_busname, _objectpath, null);
}

/**
* 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 <I>
* class extending {@link DBusInterface}
* @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.
* @param _autostart
* Disable/Enable auto-starting of services in response to calls on this object. Default is enabled; when
* calling a method with auto-start enabled, if the destination is a well-known name and is not owned the
* bus will attempt to start a process to take the name. When disabled an error is returned immediately.
* @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.
* @throws InvalidBusNameException
* If busname is incorrectly formatted
*/
public <I extends DBusInterface> I getPeerRemoteObject(String _busname, String _objectpath, Class<I> _type,
boolean _autostart) throws DBusException, InvalidBusNameException {
if (null == _busname) {
throw new InvalidBusNameException();
}

DBusObjects.requireBusNameOrConnectionId(_busname);

String unique = dbus.GetNameOwner(_busname);

return getRemoteObject(unique, _objectpath, _type, _autostart);
}

/**
* 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 <I>
* class extending {@link DBusInterface}
* @param _busname
* The bus name to connect to. Usually a well known bus name 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 <I extends DBusInterface> I getRemoteObject(String _busname, String _objectpath, Class<I> _type)
throws DBusException {
return getRemoteObject(_busname, _objectpath, _type, true);
}

/**
* 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 <I>
* class extending {@link DBusInterface}
* @param _busname
* The bus name to connect to. Usually a well known bus name 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.
* @param _autostart
* Disable/Enable auto-starting of services in response to calls on this object. Default is enabled; when
* calling a method with auto-start enabled, if the destination is a well-known name and is not owned the
* bus will attempt to start a process to take the name. When disabled an error is returned immediately.
* @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.
*/
@Override
@SuppressWarnings("unchecked")
public <I extends DBusInterface> I getRemoteObject(String _busname, String _objectpath, Class<I> _type,
boolean _autostart) throws DBusException {
if (_type == null) {
throw new ClassCastException("Not A DBus Interface");
}

DBusObjects.requireBusNameOrConnectionId(_busname);
DBusObjects.requireObjectPath(_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");
}
DBusObjects.requireDBusInterface(_type);
DBusObjects.requirePackage(_type);

RemoteObject ro = new RemoteObject(_busname, _objectpath, _type, _autostart);
I i = (I) Proxy.newProxyInstance(_type.getClassLoader(), new Class[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import org.freedesktop.dbus.connections.config.ReceivingServiceConfig;
import org.freedesktop.dbus.connections.config.TransportConfig;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.exceptions.InvalidObjectPathException;
import org.freedesktop.dbus.exceptions.MissingInterfaceImplementationException;
import org.freedesktop.dbus.interfaces.DBusInterface;
import org.freedesktop.dbus.interfaces.DBusSigHandler;
import org.freedesktop.dbus.interfaces.Introspectable;
Expand Down Expand Up @@ -145,28 +147,14 @@ public DBusInterface getRemoteObject(String _objectPath) throws DBusException {
* as the interface the remote object is exporting.
* @param <T> 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.
* @throws MissingInterfaceImplementationException If type is not a sub-type of DBusInterface
* @throws InvalidObjectPathException If busname or objectpath are invalid
*
*/
public <T extends DBusInterface> T getRemoteObject(String _objectPath, Class<T> _type) throws DBusException {
if (null == _objectPath) {
throw new DBusException("Invalid object path: null");
}
if (null == _type) {
throw new ClassCastException("Not A DBus Interface");
}

DBusObjects.requireObjectPath(_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");
}
DBusObjects.requireDBusInterface(_type);
DBusObjects.requirePackage(_type);

RemoteObject ro = new RemoteObject(null, _objectPath, _type, false);

Expand Down
Loading

0 comments on commit 39a57f3

Please sign in to comment.