Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Service to suggest addons based on running processes #3904

Merged
merged 7 commits into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions bundles/org.openhab.core.config.discovery.addon.process/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
This content is produced and maintained by the openHAB project.

* Project home: https://www.openhab.org

== Declared Project Licenses

This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.

== Source Code

https://github.com/openhab/openhab-core

29 changes: 29 additions & 0 deletions bundles/org.openhab.core.config.discovery.addon.process/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.reactor.bundles</artifactId>
<version>4.1.0-SNAPSHOT</version>
</parent>

<artifactId>org.openhab.core.config.discovery.addon.process</artifactId>

<name>openHAB Core :: Bundles :: Process-based Add-on Finder</name>

<dependencies>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.config.discovery.addon</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.addon</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.config.discovery.addon.process;

import static org.openhab.core.config.discovery.addon.AddonFinderConstants.SERVICE_NAME_PROCESS;
import static org.openhab.core.config.discovery.addon.AddonFinderConstants.SERVICE_TYPE_PROCESS;

import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.addon.AddonDiscoveryMethod;
import org.openhab.core.addon.AddonInfo;
import org.openhab.core.config.discovery.addon.AddonFinder;
import org.openhab.core.config.discovery.addon.BaseAddonFinder;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This is a {@link ProcessAddonFinder} for finding suggested add-ons by checking processes running
* on the openHAB server.
*
* @author Holger Friedrich - Initial contribution
*/
@NonNullByDefault
@Component(service = AddonFinder.class, name = ProcessAddonFinder.SERVICE_NAME)
public class ProcessAddonFinder extends BaseAddonFinder {

private static final String COMMAND = "command";

public static final String SERVICE_TYPE = SERVICE_TYPE_PROCESS;
Copy link
Contributor

@mherwege mherwege Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can eliminate these constants from AddonFinderConstants.java and define them here instead with the same logic. Only refer to ADDON_SUGGESTION_FINDER in AddonFinderConstants.java.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...but I had to make ADDON_SUGGESTION_FINDER public...

public static final String SERVICE_NAME = SERVICE_NAME_PROCESS;

private final Logger logger = LoggerFactory.getLogger(ProcessAddonFinder.class);

@Activate
public ProcessAddonFinder() {
}

// get list of running processes visible to openHAB,
// also tries to mitigate differences on different operating systems
String getProcessCommandProcess(ProcessHandle h) {
Optional<String> command = h.info().command();
if (command.isPresent())
return command.get();
Optional<String[]> args = h.info().arguments();
if (!args.isPresent())
return "";
String[] argsArray = args.get();
if (argsArray.length < 1)
return "";
return argsArray[0];
}

@Override
public Set<AddonInfo> getSuggestedAddons() {
Set<String> processList = ProcessHandle.allProcesses().map(this::getProcessCommandProcess)
holgerfriedrich marked this conversation as resolved.
Show resolved Hide resolved
.filter(Predicate.not(String::isEmpty)).collect(Collectors.toUnmodifiableSet());
Set<AddonInfo> result = new HashSet<>();
for (AddonInfo candidate : addonCandidates) {
for (AddonDiscoveryMethod method : candidate.getDiscoveryMethods().stream()
.filter(method -> SERVICE_TYPE.equals(method.getServiceType())).toList()) {
Map<String, Pattern> matchProperties = method.getMatchProperties().stream()
.collect(Collectors.toMap(property -> property.getName(), property -> property.getPattern()));

// make sure addon.xml specifies required match properties
Set<String> propertyNames = new HashSet<>(matchProperties.keySet());
if (!matchProperties.containsKey(COMMAND)) {
logger.warn("Add-on '{}' addon.xml file does not specify match property \"{}\"", candidate.getUID(),
COMMAND);
break;
}
// make sure addon.xml does not specify unknown properties
propertyNames.remove(COMMAND);
if (!propertyNames.isEmpty()) {
logger.warn("Add-on '{}' addon.xml file contains unsupported 'match-property' [{}]",
candidate.getUID(), String.join(",", propertyNames));
break;
}

// now check if a process matches the pattern defined in addon.xml
logger.debug("Checking candidate: {}", candidate.getUID());

Pattern p = matchProperties.get(COMMAND);

boolean match = processList.stream().anyMatch(c -> p.matcher(c).matches());

if (match) {
result.add(candidate);
logger.debug("Suggested add-on found: {}", candidate.getUID());
break;
}
}
}
return result;
}

@Override
public String getServiceName() {
return SERVICE_NAME;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public class AddonFinderConstants {
public static final String SERVICE_NAME_MDNS = SERVICE_TYPE_MDNS + ADDON_SUGGESTION_FINDER;
public static final String FEATURE_MDNS = ADDON_SUGGESTION_FINDER_FEATURE + SERVICE_TYPE_MDNS;

public static final String SERVICE_TYPE_PROCESS = "process";
public static final String CFG_FINDER_PROCESS = "suggestionFinderProcess";
holgerfriedrich marked this conversation as resolved.
Show resolved Hide resolved
public static final String SERVICE_NAME_PROCESS = SERVICE_TYPE_PROCESS + ADDON_SUGGESTION_FINDER;
public static final String FEATURE_PROCESS = ADDON_SUGGESTION_FINDER_FEATURE + SERVICE_TYPE_PROCESS;

public static final String SERVICE_TYPE_UPNP = "upnp";
public static final String CFG_FINDER_UPNP = "suggestionFinderUpnp";
public static final String SERVICE_NAME_UPNP = SERVICE_TYPE_UPNP + ADDON_SUGGESTION_FINDER;
Expand Down
1 change: 1 addition & 0 deletions bundles/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<module>org.openhab.core.config.discovery</module>
<module>org.openhab.core.config.discovery.addon</module>
<module>org.openhab.core.config.discovery.addon.mdns</module>
<module>org.openhab.core.config.discovery.addon.process</module>
<module>org.openhab.core.config.discovery.addon.upnp</module>
<module>org.openhab.core.config.discovery.mdns</module>
<module>org.openhab.core.config.discovery.usbserial</module>
Expand Down