forked from openhab/openhab-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[marketplace] Add add-on handler for block libraries (openhab#2598)
Related to openhab/openhab-webui#1225. This add-on handler supports installing block libraries in the UIComponentRegistry, `ui:blocks` namespace. It is very similar to the CommunityUIWidgetAddonHandler, as the format is the same, so are the features and implementation, the only differences being: - Supported content type: `application/vnd.openhab.uicomponent;type=blocks` (vs. `application/vnd.openhab.uicomponent;type=widget`) - Discourse category nb.: 76 (vs. 75) - Inferred Add-on type: "automation" (vs. "ui") Signed-off-by: Yannick Schaus <github@schaus.net>
- Loading branch information
Showing
2 changed files
with
127 additions
and
0 deletions.
There are no files selected for viewing
121 changes: 121 additions & 0 deletions
121
...g/openhab/core/addon/marketplace/internal/community/CommunityBlockLibaryAddonHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
/** | ||
* Copyright (c) 2010-2021 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.marketplace.internal.community; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.net.URL; | ||
import java.nio.charset.StandardCharsets; | ||
import java.text.SimpleDateFormat; | ||
|
||
import org.eclipse.jdt.annotation.NonNullByDefault; | ||
import org.openhab.core.addon.Addon; | ||
import org.openhab.core.addon.marketplace.MarketplaceAddonHandler; | ||
import org.openhab.core.addon.marketplace.MarketplaceHandlerException; | ||
import org.openhab.core.ui.components.RootUIComponent; | ||
import org.openhab.core.ui.components.UIComponentRegistry; | ||
import org.openhab.core.ui.components.UIComponentRegistryFactory; | ||
import org.osgi.service.component.annotations.Activate; | ||
import org.osgi.service.component.annotations.Component; | ||
import org.osgi.service.component.annotations.Reference; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; | ||
|
||
/** | ||
* A {@link MarketplaceAddonHandler} implementation, which handles block libraries as YAML files and installs | ||
* them by adding them to the {@link UIComponentRegistry} for the ui:blocks namespace. | ||
* | ||
* @author Yannick Schaus - Initial contribution and API | ||
* | ||
*/ | ||
@Component(immediate = true) | ||
@NonNullByDefault | ||
public class CommunityBlockLibaryAddonHandler implements MarketplaceAddonHandler { | ||
private static final String YAML_DOWNLOAD_URL_PROPERTY = "yaml_download_url"; | ||
private static final String YAML_CONTENT_PROPERTY = "yaml_content"; | ||
private static final String BLOCKLIBRARIES_CONTENT_TYPE = "application/vnd.openhab.uicomponent;type=blocks"; | ||
|
||
private final Logger logger = LoggerFactory.getLogger(CommunityBlockLibaryAddonHandler.class); | ||
ObjectMapper yamlMapper; | ||
|
||
private UIComponentRegistry blocksRegistry; | ||
|
||
@Activate | ||
public CommunityBlockLibaryAddonHandler(final @Reference UIComponentRegistryFactory uiComponentRegistryFactory) { | ||
this.blocksRegistry = uiComponentRegistryFactory.getRegistry("ui:blocks"); | ||
this.yamlMapper = new ObjectMapper(new YAMLFactory()); | ||
yamlMapper.findAndRegisterModules(); | ||
this.yamlMapper.setDateFormat(new SimpleDateFormat("MMM d, yyyy, hh:mm:ss aa")); | ||
} | ||
|
||
@Override | ||
public boolean supports(String type, String contentType) { | ||
return "automation".equals(type) && BLOCKLIBRARIES_CONTENT_TYPE.equals(contentType); | ||
} | ||
|
||
@Override | ||
public boolean isInstalled(String id) { | ||
return blocksRegistry.getAll().stream().anyMatch(w -> w.hasTag(id)); | ||
} | ||
|
||
@Override | ||
public void install(Addon addon) throws MarketplaceHandlerException { | ||
try { | ||
String yamlDownloadUrl = (String) addon.getProperties().get(YAML_DOWNLOAD_URL_PROPERTY); | ||
String yamlContent = (String) addon.getProperties().get(YAML_CONTENT_PROPERTY); | ||
|
||
if (yamlDownloadUrl != null) { | ||
addWidgetAsYAML(addon.getId(), getWidgetFromURL(yamlDownloadUrl)); | ||
} else if (yamlContent != null) { | ||
addWidgetAsYAML(addon.getId(), yamlContent); | ||
} else { | ||
throw new IllegalArgumentException("Couldn't find the block library in the add-on entry"); | ||
} | ||
} catch (IOException e) { | ||
logger.error("Block library from marketplace cannot be downloaded: {}", e.getMessage()); | ||
throw new MarketplaceHandlerException("Widget cannot be downloaded.", e); | ||
} catch (Exception e) { | ||
logger.error("Block library from marketplace is invalid: {}", e.getMessage()); | ||
throw new MarketplaceHandlerException("Widget is not valid.", e); | ||
} | ||
} | ||
|
||
@Override | ||
public void uninstall(Addon addon) throws MarketplaceHandlerException { | ||
blocksRegistry.getAll().stream().filter(w -> w.hasTag(addon.getId())).forEach(w -> { | ||
blocksRegistry.remove(w.getUID()); | ||
}); | ||
} | ||
|
||
private String getWidgetFromURL(String urlString) throws IOException { | ||
URL u = new URL(urlString); | ||
try (InputStream in = u.openStream()) { | ||
return new String(in.readAllBytes(), StandardCharsets.UTF_8); | ||
} | ||
} | ||
|
||
private void addWidgetAsYAML(String id, String yaml) { | ||
try { | ||
RootUIComponent widget = yamlMapper.readValue(yaml, RootUIComponent.class); | ||
// add a tag with the add-on ID to be able to identify the block library in the registry | ||
widget.addTag(id); | ||
blocksRegistry.add(widget); | ||
} catch (IOException e) { | ||
logger.error("Unable to parse YAML: {}", e.getMessage()); | ||
throw new IllegalArgumentException("Unable to parse YAML"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters