diff --git a/bom/openhab-core/pom.xml b/bom/openhab-core/pom.xml index 8346e8dd5..b13d80de9 100644 --- a/bom/openhab-core/pom.xml +++ b/bom/openhab-core/pom.xml @@ -316,6 +316,12 @@ ${project.version} compile + + org.openhab.core.bundles + org.openhab.core.config.discovery.addon.process + ${project.version} + compile + org.openhab.core.bundles org.openhab.core.config.discovery.addon.upnp diff --git a/bundles/org.openhab.core.config.discovery.addon.process/.classpath b/bundles/org.openhab.core.config.discovery.addon.process/.classpath new file mode 100644 index 000000000..d3d6b3c11 --- /dev/null +++ b/bundles/org.openhab.core.config.discovery.addon.process/.classpath @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.core.config.discovery.addon.process/.project b/bundles/org.openhab.core.config.discovery.addon.process/.project new file mode 100644 index 000000000..fefa8799d --- /dev/null +++ b/bundles/org.openhab.core.config.discovery.addon.process/.project @@ -0,0 +1,23 @@ + + + org.openhab.core.config.discovery.addon.process + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.jdt.core.javanature + + diff --git a/bundles/org.openhab.core.config.discovery.addon.process/NOTICE b/bundles/org.openhab.core.config.discovery.addon.process/NOTICE new file mode 100644 index 000000000..6c17d0d8a --- /dev/null +++ b/bundles/org.openhab.core.config.discovery.addon.process/NOTICE @@ -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 + diff --git a/bundles/org.openhab.core.config.discovery.addon.process/pom.xml b/bundles/org.openhab.core.config.discovery.addon.process/pom.xml new file mode 100644 index 000000000..9cab7b67f --- /dev/null +++ b/bundles/org.openhab.core.config.discovery.addon.process/pom.xml @@ -0,0 +1,29 @@ + + + + 4.0.0 + + + org.openhab.core.bundles + org.openhab.core.reactor.bundles + 4.1.0-SNAPSHOT + + + org.openhab.core.config.discovery.addon.process + + openHAB Core :: Bundles :: Process-based Suggested Add-on Finder + + + + org.openhab.core.bundles + org.openhab.core.config.discovery.addon + ${project.version} + + + org.openhab.core.bundles + org.openhab.core.addon + ${project.version} + + + diff --git a/bundles/org.openhab.core.config.discovery.addon.process/src/main/java/org/openhab/core/config/discovery/addon/process/ProcessAddonFinder.java b/bundles/org.openhab.core.config.discovery.addon.process/src/main/java/org/openhab/core/config/discovery/addon/process/ProcessAddonFinder.java new file mode 100644 index 000000000..316be24d9 --- /dev/null +++ b/bundles/org.openhab.core.config.discovery.addon.process/src/main/java/org/openhab/core/config/discovery/addon/process/ProcessAddonFinder.java @@ -0,0 +1,126 @@ +/** + * 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.ADDON_SUGGESTION_FINDER; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; +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.addon.AddonMatchProperty; +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 { + + public static final String SERVICE_TYPE = "process"; + public static final String CFG_FINDER_PROCESS = "suggestionFinderProcess"; + public static final String SERVICE_NAME = SERVICE_TYPE + ADDON_SUGGESTION_FINDER; + + private static final String COMMAND = "command"; + + 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 command = h.info().command(); + if (command.isPresent()) + return command.get(); + Optional args = h.info().arguments(); + if (!args.isPresent()) + return ""; + String[] argsArray = args.get(); + if (argsArray.length < 1) + return ""; + return argsArray[0]; + } + + @Override + public Set getSuggestedAddons() { + logger.trace("ProcessAddonFinder::getSuggestedAddons"); + Set result = new HashSet<>(); + Set processList = Collections.emptySet(); + try { + processList = ProcessHandle.allProcesses().map(this::getProcessCommandProcess) + .filter(Predicate.not(String::isEmpty)).collect(Collectors.toUnmodifiableSet()); + } catch (SecurityException | UnsupportedOperationException unused) { + logger.info("Cannot obtain process list, suggesting add-ons based on running processes is not possible"); + return result; + } + + for (AddonInfo candidate : addonCandidates) { + for (AddonDiscoveryMethod method : candidate.getDiscoveryMethods().stream() + .filter(method -> SERVICE_TYPE.equals(method.getServiceType())).toList()) { + + List matchProperties = method.getMatchProperties(); + List commands = matchProperties.stream() + .filter(amp -> COMMAND.equals(amp.getName())).collect(Collectors.toUnmodifiableList()); + + if (matchProperties.size() != commands.size()) { + logger.warn("Add-on '{}' addon.xml file contains unsupported 'match-property'", candidate.getUID()); + } + + if (commands.isEmpty()) { + logger.warn("Add-on '{}' addon.xml file does not specify match property \"{}\"", candidate.getUID(), + COMMAND); + break; + } + + // now check if a process matches the pattern defined in addon.xml + logger.debug("Checking candidate: {}", candidate.getUID()); + + for (AddonMatchProperty command : commands) { + logger.trace("Candidate {}, pattern \"{}\"", candidate.getUID(), command.getRegex()); + boolean match = processList.stream().anyMatch(c -> command.getPattern().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; + } +} diff --git a/bundles/org.openhab.core.config.discovery.addon/src/main/java/org/openhab/core/config/discovery/addon/AddonFinderConstants.java b/bundles/org.openhab.core.config.discovery.addon/src/main/java/org/openhab/core/config/discovery/addon/AddonFinderConstants.java index 596498898..76bef9d57 100644 --- a/bundles/org.openhab.core.config.discovery.addon/src/main/java/org/openhab/core/config/discovery/addon/AddonFinderConstants.java +++ b/bundles/org.openhab.core.config.discovery.addon/src/main/java/org/openhab/core/config/discovery/addon/AddonFinderConstants.java @@ -25,7 +25,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; @NonNullByDefault public class AddonFinderConstants { - private static final String ADDON_SUGGESTION_FINDER = "-addon-suggestion-finder"; + public static final String ADDON_SUGGESTION_FINDER = "-addon-suggestion-finder"; private static final String ADDON_SUGGESTION_FINDER_FEATURE = "openhab-core-config-discovery-addon-"; public static final String SERVICE_TYPE_MDNS = "mdns"; diff --git a/bundles/pom.xml b/bundles/pom.xml index 01799d771..ad85d6f1b 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -32,6 +32,7 @@ org.openhab.core.config.discovery org.openhab.core.config.discovery.addon org.openhab.core.config.discovery.addon.mdns + org.openhab.core.config.discovery.addon.process org.openhab.core.config.discovery.addon.upnp org.openhab.core.config.discovery.mdns org.openhab.core.config.discovery.usbserial diff --git a/features/karaf/openhab-core/src/main/feature/feature.xml b/features/karaf/openhab-core/src/main/feature/feature.xml index 5062c2ead..9ef66a80f 100644 --- a/features/karaf/openhab-core/src/main/feature/feature.xml +++ b/features/karaf/openhab-core/src/main/feature/feature.xml @@ -44,6 +44,7 @@ mvn:org.openhab.core.bundles/org.openhab.core.automation/${project.version} mvn:org.openhab.core.bundles/org.openhab.core.config.core/${project.version} mvn:org.openhab.core.bundles/org.openhab.core.config.discovery/${project.version} + mvn:org.openhab.core.bundles/org.openhab.core.config.discovery.addon.process/${project.version} mvn:org.openhab.core.bundles/org.openhab.core.config.dispatch/${project.version} mvn:org.openhab.core.bundles/org.openhab.core/${project.version} mvn:org.openhab.osgiify/io.methvin.directory-watcher/0.18.0