Add Eclipse Add-on Service (#3406)

This service provides add-on information when debugging in Eclipse so it is possible to add Things based on the installed bindings and configure installed add-ons in the UI.
Replaces the Sample Add-on Service.

Also shows the "Add-on Management" configuration which allows for configuring if incompatible add-ons are included.

Signed-off-by: Wouter Born <github@maindrain.net>
pull/3413/head
Wouter Born 2023-03-02 07:41:49 +01:00 committed by GitHub
parent 48c44a04d8
commit 59c5133815
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 285 additions and 242 deletions

View File

@ -514,6 +514,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.addon.eclipse</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.addon.marketplace</artifactId>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.core.addon.sample</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@ -10,9 +10,9 @@
<version>4.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.core.addon.sample</artifactId>
<artifactId>org.openhab.core.addon.eclipse</artifactId>
<name>openHAB Core :: Bundles :: Sample Add-on Service</name>
<name>openHAB Core :: Bundles :: Eclipse Add-on Service</name>
<dependencies>
<dependency>

View File

@ -0,0 +1,193 @@
/**
* 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.addon.eclipse.internal;
import static java.util.Map.entry;
import static org.openhab.core.addon.AddonType.*;
import java.net.URI;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.addon.Addon;
import org.openhab.core.addon.AddonInfo;
import org.openhab.core.addon.AddonInfoRegistry;
import org.openhab.core.addon.AddonService;
import org.openhab.core.addon.AddonType;
import org.openhab.core.config.core.ConfigurableService;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
/**
* This is an implementation of an {@link AddonService} that can be used when debugging in Eclipse.
*
* @author Wouter Born - Initial contribution
*/
@Component(name = "org.openhab.addons")
@NonNullByDefault
@ConfigurableService(category = "system", label = "Add-on Management", description_uri = EclipseAddonService.CONFIG_URI)
public class EclipseAddonService implements AddonService {
public static final String CONFIG_URI = "system:addons";
private static final String SERVICE_ID = "eclipse";
private static final String ADDON_ID_PREFIX = SERVICE_ID + ":";
private static final String ADDONS_CONTENT_TYPE = "application/vnd.openhab.bundle";
private static final String ADDONS_AUTHOR = "openHAB";
private static final String BUNDLE_SYMBOLIC_NAME_PREFIX = "org.openhab.";
private static final Map<String, String> ADDON_BUNDLE_TYPE_MAP = Map.ofEntries(
entry(AUTOMATION.getId(), "automation"), //
entry(BINDING.getId(), "binding"), //
entry(MISC.getId(), "io"), //
entry(PERSISTENCE.getId(), "persistence"), //
entry(TRANSFORMATION.getId(), "transform"), //
entry(UI.getId(), "ui"), //
entry(VOICE.getId(), "voice"));
private static final Map<String, String> BUNDLE_ADDON_TYPE_MAP = ADDON_BUNDLE_TYPE_MAP.entrySet().stream()
.collect(Collectors.toMap(Entry::getValue, Entry::getKey));
private static final String DOCUMENTATION_URL_PREFIX = "https://www.openhab.org/addons/";
private static final Map<String, String> DOCUMENTATION_URL_FORMATS = Map.ofEntries(
entry(AUTOMATION.getId(), DOCUMENTATION_URL_PREFIX + "automation/%s/"), //
entry(BINDING.getId(), DOCUMENTATION_URL_PREFIX + "bindings/%s/"), //
entry(MISC.getId(), DOCUMENTATION_URL_PREFIX + "integrations/%s/"), //
entry(PERSISTENCE.getId(), DOCUMENTATION_URL_PREFIX + "persistence/%s/"), //
entry(TRANSFORMATION.getId(), DOCUMENTATION_URL_PREFIX + "transformations/%s/"), //
entry(UI.getId(), DOCUMENTATION_URL_PREFIX + "ui/%s/"), //
entry(VOICE.getId(), DOCUMENTATION_URL_PREFIX + "voice/%s/"));
private final BundleContext bundleContext;
private final AddonInfoRegistry addonInfoRegistry;
@Activate
public EclipseAddonService(BundleContext bundleContext, @Reference AddonInfoRegistry addonInfoRegistry) {
this.bundleContext = bundleContext;
this.addonInfoRegistry = addonInfoRegistry;
}
@Deactivate
protected void deactivate() {
}
@Override
public String getId() {
return SERVICE_ID;
}
@Override
public String getName() {
return "Eclipse Add-on Service";
}
@Override
public void refreshSource() {
}
@Override
public void install(String id) {
throw new UnsupportedOperationException(getName() + " does not support installing add-ons");
}
@Override
public void uninstall(String id) {
throw new UnsupportedOperationException(getName() + " does not support uninstalling add-ons");
}
private boolean isAddon(Bundle bundle) {
String symbolicName = bundle.getSymbolicName();
String[] segments = symbolicName.split("\\.");
return symbolicName.startsWith(BUNDLE_SYMBOLIC_NAME_PREFIX) && bundle.getState() == Bundle.ACTIVE
&& segments.length >= 4 && ADDON_BUNDLE_TYPE_MAP.containsValue(segments[2]);
}
private Addon getAddon(Bundle bundle, @Nullable Locale locale) {
String symbolicName = bundle.getSymbolicName();
String[] segments = symbolicName.split("\\.");
String type = Objects.requireNonNull(BUNDLE_ADDON_TYPE_MAP.get(segments[2]));
String name = segments[3];
String uid = type + Addon.ADDON_SEPARATOR + name;
Addon.Builder addon = Addon.create(ADDON_ID_PREFIX + uid).withType(type).withId(name)
.withContentType(ADDONS_CONTENT_TYPE).withVersion(bundle.getVersion().toString())
.withAuthor(ADDONS_AUTHOR, true).withInstalled(true);
AddonInfo addonInfo = addonInfoRegistry.getAddonInfo(uid, locale);
if (addonInfo != null) {
// only enrich if this add-on is installed, otherwise wrong data might be added
addon = addon.withLabel(addonInfo.getName()).withDescription(addonInfo.getDescription())
.withCountries(addonInfo.getCountries()).withLink(getDefaultDocumentationLink(type, name))
.withConfigDescriptionURI(addonInfo.getConfigDescriptionURI());
} else {
addon = addon.withLabel(name).withLink(getDefaultDocumentationLink(type, name));
}
addon.withLoggerPackages(List.of(symbolicName));
return addon.build();
}
@Override
public List<Addon> getAddons(@Nullable Locale locale) {
return Arrays.stream(bundleContext.getBundles()) //
.filter(this::isAddon) //
.map(bundle -> getAddon(bundle, locale)) //
.sorted(Comparator.comparing(Addon::getLabel)) //
.toList();
}
private @Nullable String getDefaultDocumentationLink(String type, String name) {
String format = DOCUMENTATION_URL_FORMATS.get(type);
return format == null ? null : String.format(format, name);
}
@Override
public @Nullable Addon getAddon(String uid, @Nullable Locale locale) {
String id = uid.replaceFirst(ADDON_ID_PREFIX, "");
String[] segments = id.split(Addon.ADDON_SEPARATOR);
String symbolicName = BUNDLE_SYMBOLIC_NAME_PREFIX + ADDON_BUNDLE_TYPE_MAP.get(segments[0]) + "." + segments[1];
return Arrays.stream(bundleContext.getBundles()) //
.filter(bundle -> bundle.getSymbolicName().equals(symbolicName)) //
.filter(this::isAddon) //
.map(bundle -> getAddon(bundle, locale)) //
.findFirst().orElse(null);
}
@Override
public List<AddonType> getTypes(@Nullable Locale locale) {
return AddonType.DEFAULT_TYPES;
}
@Override
public @Nullable String getAddonId(URI extensionURI) {
return null;
}
}

View File

@ -20,7 +20,6 @@ import java.util.Dictionary;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@ -57,15 +56,6 @@ public abstract class AbstractRemoteAddonService implements AddonService {
static final String CONFIG_REMOTE_ENABLED = "remote";
static final String CONFIG_INCLUDE_INCOMPATIBLE = "includeIncompatible";
protected static final Map<String, AddonType> TAG_ADDON_TYPE_MAP = Map.of( //
"automation", new AddonType("automation", "Automation"), //
"binding", new AddonType("binding", "Bindings"), //
"misc", new AddonType("misc", "Misc"), //
"persistence", new AddonType("persistence", "Persistence"), //
"transformation", new AddonType("transformation", "Transformations"), //
"ui", new AddonType("ui", "User Interfaces"), //
"voice", new AddonType("voice", "Voice"));
protected final BundleVersion coreVersion;
protected final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").create();
@ -163,7 +153,7 @@ public abstract class AbstractRemoteAddonService implements AddonService {
@Override
public List<AddonType> getTypes(@Nullable Locale locale) {
return new ArrayList<>(TAG_ADDON_TYPE_MAP.values());
return AddonType.DEFAULT_TYPES;
}
@Override

View File

@ -239,14 +239,15 @@ public class CommunityMarketplaceAddonService extends AbstractRemoteAddonService
private @Nullable AddonType getAddonType(@Nullable Integer category, List<String> tags) {
// check if we can determine the addon type from the category
if (RULETEMPLATES_CATEGORY.equals(category)) {
return TAG_ADDON_TYPE_MAP.get("automation");
return AddonType.AUTOMATION;
} else if (UIWIDGETS_CATEGORY.equals(category)) {
return TAG_ADDON_TYPE_MAP.get("ui");
return AddonType.UI;
} else if (BLOCKLIBRARIES_CATEGORY.equals(category)) {
return TAG_ADDON_TYPE_MAP.get("automation");
return AddonType.AUTOMATION;
} else if (BUNDLES_CATEGORY.equals(category)) {
// try to get it from tags if we have tags
return tags.stream().map(TAG_ADDON_TYPE_MAP::get).filter(Objects::nonNull).findFirst().orElse(null);
return AddonType.DEFAULT_TYPES.stream().filter(type -> tags.contains(type.getId())).findFirst()
.orElse(null);
}
// or return null

View File

@ -1,179 +0,0 @@
/**
* 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.addon.sample.internal;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.addon.Addon;
import org.openhab.core.addon.AddonEventFactory;
import org.openhab.core.addon.AddonService;
import org.openhab.core.addon.AddonType;
import org.openhab.core.events.Event;
import org.openhab.core.events.EventPublisher;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
/**
* This is an implementation of an {@link AddonService} that can be used as a dummy service for testing the
* functionality.
* It is not meant to be used anywhere productively.
*
* @author Kai Kreuzer - Initial contribution
*/
@Component
@NonNullByDefault
public class SampleAddonService implements AddonService {
private static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.";
private static final String[] COLOR_VALUES = new String[] { "80", "C8", "FF" };
private final EventPublisher eventPublisher;
private List<AddonType> types = new ArrayList<>(3);
private Map<String, Addon> extensions = new HashMap<>(30);
@Activate
public SampleAddonService(final @Reference EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
@Activate
protected void activate() {
types.add(new AddonType("binding", "Bindings"));
types.add(new AddonType("ui", "User Interfaces"));
types.add(new AddonType("persistence", "Persistence Services"));
for (AddonType type : types) {
for (int i = 0; i < 10; i++) {
String id = type.getId() + Integer.toString(i);
boolean installed = Math.random() > 0.5;
byte[] array = new byte[5];
new Random().nextBytes(array);
String name = new String(array, StandardCharsets.UTF_8);
String typeId = type.getId();
String label = name + " " + typeId.substring(0, 1).toUpperCase() + typeId.substring(1).toLowerCase();
String version = "1.0";
String link = (Math.random() < 0.5) ? null : "http://lmgtfy.com/?q=" + name;
String description = createDescription();
String backgroundColor = createRandomColor();
Addon extension = Addon.create(id).withType(typeId).withLabel(label).withVersion(version)
.withMaturity("stable").withContentType("example/vnd.openhab.addon").withLink(link)
.withAuthor("John Doe", false).withInstalled(installed).withDescription(description)
.withBackgroundColor(backgroundColor).build();
extensions.put(extension.getUid(), extension);
}
}
}
private static final Random RANDOM = new Random();
private String createRandomColor() {
StringBuilder ret = new StringBuilder("#");
for (int i = 0; i < 3; i++) {
ret.append(COLOR_VALUES[RANDOM.nextInt(COLOR_VALUES.length)]);
}
return ret.toString();
}
private String createDescription() {
int index = LOREM_IPSUM.indexOf(" ", RANDOM.nextInt(LOREM_IPSUM.length()));
if (index < 0) {
index = LOREM_IPSUM.length();
}
return LOREM_IPSUM.substring(0, index);
}
@Deactivate
protected void deactivate() {
types.clear();
extensions.clear();
}
@Override
public String getId() {
return "sample";
}
@Override
public String getName() {
return "Sample Add-on Service";
}
@Override
public void refreshSource() {
}
@Override
public void install(String id) {
try {
Thread.sleep((long) (Math.random() * 10000));
Addon extension = getAddon(id, null);
extension.setInstalled(true);
postInstalledEvent(id);
} catch (InterruptedException e) {
}
}
@Override
public void uninstall(String id) {
try {
Thread.sleep((long) (Math.random() * 5000));
Addon extension = getAddon(id, null);
extension.setInstalled(false);
postUninstalledEvent(id);
} catch (InterruptedException e) {
}
}
@Override
public List<Addon> getAddons(@Nullable Locale locale) {
return new ArrayList<>(extensions.values());
}
@Override
public @Nullable Addon getAddon(String id, @Nullable Locale locale) {
return extensions.get(id);
}
@Override
public List<AddonType> getTypes(@Nullable Locale locale) {
return types;
}
@Override
public @Nullable String getAddonId(URI extensionURI) {
return null;
}
private void postInstalledEvent(String extensionId) {
Event event = AddonEventFactory.createAddonInstalledEvent(extensionId);
eventPublisher.post(event);
}
private void postUninstalledEvent(String extensionId) {
Event event = AddonEventFactory.createAddonUninstalledEvent(extensionId);
eventPublisher.post(event);
}
}

View File

@ -6,7 +6,12 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src/generated/java"/>
<classpathentry including="**/*.java" kind="src" output="target/classes" path="src/generated/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<attributes>
<attribute name="maven.pomderived" value="true"/>
@ -26,5 +31,10 @@
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/generated">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -12,6 +12,8 @@
*/
package org.openhab.core.addon;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@ -23,6 +25,17 @@ import org.eclipse.jdt.annotation.Nullable;
@NonNullByDefault
public class AddonType {
public static final AddonType AUTOMATION = new AddonType("automation", "Automation");
public static final AddonType BINDING = new AddonType("binding", "Bindings");
public static final AddonType MISC = new AddonType("misc", "Misc");
public static final AddonType PERSISTENCE = new AddonType("persistence", "Persistence");
public static final AddonType TRANSFORMATION = new AddonType("transformation", "Transformations");
public static final AddonType UI = new AddonType("ui", "User Interfaces");
public static final AddonType VOICE = new AddonType("voice", "Voice");
public static final List<AddonType> DEFAULT_TYPES = List.of(AUTOMATION, BINDING, MISC, PERSISTENCE, TRANSFORMATION,
UI, VOICE);
private final String id;
private final String label;
@ -64,10 +77,7 @@ public class AddonType {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
if ((obj == null) || (getClass() != obj.getClass())) {
return false;
}
return id.equals(((AddonType) obj).id);

View File

@ -50,6 +50,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.OpenHAB;
import org.openhab.core.addon.AddonEventFactory;
import org.openhab.core.addon.AddonType;
import org.openhab.core.common.NamedThreadFactory;
import org.openhab.core.config.core.ConfigParser;
import org.openhab.core.config.core.ConfigurableService;
@ -81,17 +82,6 @@ public class FeatureInstaller implements ConfigurationListener {
protected static final String CONFIG_URI = "system:addons";
public static final String EXTENSION_TYPE_AUTOMATION = "automation";
public static final String EXTENSION_TYPE_BINDING = "binding";
public static final String EXTENSION_TYPE_MISC = "misc";
public static final String EXTENSION_TYPE_PERSISTENCE = "persistence";
public static final String EXTENSION_TYPE_TRANSFORMATION = "transformation";
public static final String EXTENSION_TYPE_UI = "ui";
public static final String EXTENSION_TYPE_VOICE = "voice";
public static final Set<String> EXTENSION_TYPES = Set.of(EXTENSION_TYPE_AUTOMATION, EXTENSION_TYPE_BINDING,
EXTENSION_TYPE_MISC, EXTENSION_TYPE_PERSISTENCE, EXTENSION_TYPE_TRANSFORMATION, EXTENSION_TYPE_UI,
EXTENSION_TYPE_VOICE);
public static final String PREFIX = "openhab-";
public static final String PREFIX_PACKAGE = "package-";
public static final String MINIMAL_PACKAGE = "minimal";
@ -101,6 +91,9 @@ public class FeatureInstaller implements ConfigurationListener {
private static final String ADDONS_PID = "org.openhab.addons";
private static final String PROPERTY_MVN_REPOS = "org.ops4j.pax.url.mvn.repositories";
public static final List<String> ADDON_TYPES = AddonType.DEFAULT_TYPES.stream().map(AddonType::getId)
.collect(Collectors.toList());
private final Logger logger = LoggerFactory.getLogger(FeatureInstaller.class);
private final ConfigurationAdmin configurationAdmin;
@ -388,7 +381,7 @@ public class FeatureInstaller implements ConfigurationListener {
final Set<String> targetAddons = new HashSet<>(); // the target we want to have installed afterwards
final Set<String> installAddons = new HashSet<>(); // the ones to be installed (the diff)
for (String type : EXTENSION_TYPES) {
for (String type : ADDON_TYPES) {
Object configValue = config.get(type);
if (configValue instanceof String addonString) {
try {

View File

@ -12,11 +12,15 @@
*/
package org.openhab.core.karaf.internal;
import static java.util.Map.entry;
import static org.openhab.core.addon.AddonType.*;
import java.net.URI;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeaturesService;
@ -44,14 +48,17 @@ import org.slf4j.LoggerFactory;
public class KarafAddonService implements AddonService {
private static final String ADDONS_CONTENT_TYPE = "application/vnd.openhab.feature;type=karaf";
private static final String ADDONS_AUTHOR = "openHAB";
private static final List<AddonType> ADDON_TYPES = List.of( //
new AddonType(FeatureInstaller.EXTENSION_TYPE_AUTOMATION, "Automation"), //
new AddonType(FeatureInstaller.EXTENSION_TYPE_BINDING, "Bindings"), //
new AddonType(FeatureInstaller.EXTENSION_TYPE_MISC, "Misc"), //
new AddonType(FeatureInstaller.EXTENSION_TYPE_VOICE, "Voice"), //
new AddonType(FeatureInstaller.EXTENSION_TYPE_PERSISTENCE, "Persistence"), //
new AddonType(FeatureInstaller.EXTENSION_TYPE_TRANSFORMATION, "Transformations"), //
new AddonType(FeatureInstaller.EXTENSION_TYPE_UI, "User Interfaces"));
private static final String DOCUMENTATION_URL_PREFIX = "https://www.openhab.org/addons/";
private static final Map<String, String> DOCUMENTATION_URL_FORMATS = Map.ofEntries(
entry(AUTOMATION.getId(), DOCUMENTATION_URL_PREFIX + "automation/%s/"), //
entry(BINDING.getId(), DOCUMENTATION_URL_PREFIX + "bindings/%s/"), //
entry(MISC.getId(), DOCUMENTATION_URL_PREFIX + "integrations/%s/"), //
entry(PERSISTENCE.getId(), DOCUMENTATION_URL_PREFIX + "persistence/%s/"), //
entry(TRANSFORMATION.getId(), DOCUMENTATION_URL_PREFIX + "transformations/%s/"), //
entry(UI.getId(), DOCUMENTATION_URL_PREFIX + "ui/%s/"), //
entry(VOICE.getId(), DOCUMENTATION_URL_PREFIX + "voice/%s/"));
private final Logger logger = LoggerFactory.getLogger(KarafAddonService.class);
@ -95,7 +102,7 @@ public class KarafAddonService implements AddonService {
private boolean isAddon(Feature feature) {
return feature.getName().startsWith(FeatureInstaller.PREFIX)
&& FeatureInstaller.EXTENSION_TYPES.contains(getType(feature.getName()));
&& FeatureInstaller.ADDON_TYPES.contains(getAddonType(feature.getName()));
}
@Override
@ -111,24 +118,13 @@ public class KarafAddonService implements AddonService {
}
private @Nullable String getDefaultDocumentationLink(String type, String name) {
return switch (type) {
case FeatureInstaller.EXTENSION_TYPE_AUTOMATION -> "https://www.openhab.org/addons/automation/" + name
+ "/";
case FeatureInstaller.EXTENSION_TYPE_BINDING -> "https://www.openhab.org/addons/bindings/" + name + "/";
case FeatureInstaller.EXTENSION_TYPE_MISC -> "https://www.openhab.org/addons/integrations/" + name + "/";
case FeatureInstaller.EXTENSION_TYPE_PERSISTENCE -> "https://www.openhab.org/addons/persistence/" + name
+ "/";
case FeatureInstaller.EXTENSION_TYPE_TRANSFORMATION -> "https://www.openhab.org/addons/transformations/"
+ name + "/";
case FeatureInstaller.EXTENSION_TYPE_VOICE -> "https://www.openhab.org/addons/voice/" + name + "/";
case FeatureInstaller.EXTENSION_TYPE_UI -> "https://www.openhab.org/addons/ui/" + name + "/";
default -> null;
};
String format = DOCUMENTATION_URL_FORMATS.get(type);
return format == null ? null : String.format(format, name);
}
private Addon getAddon(Feature feature, @Nullable Locale locale) {
String name = getName(feature.getName());
String type = getType(feature.getName());
String type = getAddonType(feature.getName());
String uid = type + Addon.ADDON_SEPARATOR + name;
boolean isInstalled = featuresService.isInstalled(feature);
@ -159,17 +155,17 @@ public class KarafAddonService implements AddonService {
@Override
public List<AddonType> getTypes(@Nullable Locale locale) {
return ADDON_TYPES;
return AddonType.DEFAULT_TYPES;
}
@Override
public void install(String id) {
featureInstaller.addAddon(getType(id), getName(id));
featureInstaller.addAddon(getAddonType(id), getName(id));
}
@Override
public void uninstall(String id) {
featureInstaller.removeAddon(getType(id), getName(id));
featureInstaller.removeAddon(getAddonType(id), getName(id));
}
@Override
@ -177,7 +173,7 @@ public class KarafAddonService implements AddonService {
return null;
}
private String getType(String name) {
private String getAddonType(String name) {
String str = name.startsWith(FeatureInstaller.PREFIX) ? name.substring(FeatureInstaller.PREFIX.length()) : name;
int index = str.indexOf(Addon.ADDON_SEPARATOR);
return index == -1 ? str : str.substring(0, index);

View File

@ -17,9 +17,10 @@
<name>openHAB Core :: Bundles</name>
<modules>
<module>org.openhab.core.addon</module>
<module>org.openhab.core.addon.eclipse</module>
<module>org.openhab.core.addon.marketplace</module>
<module>org.openhab.core.addon.marketplace.karaf</module>
<module>org.openhab.core.addon</module>
<module>org.openhab.core.auth.jaas</module>
<module>org.openhab.core.auth.oauth2client</module>
<module>org.openhab.core.automation</module>
@ -39,7 +40,6 @@
<module>org.openhab.core</module>
<module>org.openhab.core.audio</module>
<module>org.openhab.core.ephemeris</module>
<module>org.openhab.core.addon.sample</module>
<module>org.openhab.core.id</module>
<module>org.openhab.core.persistence</module>
<module>org.openhab.core.semantics</module>