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
parent
48c44a04d8
commit
59c5133815
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue