Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Initial contribution of an IoT Market extension service #3076

Merged
merged 10 commits into from
Mar 5, 2017
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public Response getById(@HeaderParam("Accept-Language") @ApiParam(value = "langu
}

@POST
@Path("/{extensionId: [a-zA-Z_0-9-]*}/install")
@Path("/{extensionId: [a-zA-Z_0-9-:]*}/install")
@ApiOperation(value = "Installs the extension with the given ID.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
public Response installExtension(
Expand All @@ -149,7 +149,7 @@ public void run() {
}

@POST
@Path("/{extensionId: [a-zA-Z_0-9-]*}/uninstall")
@Path("/{extensionId: [a-zA-Z_0-9-:]*}/uninstall")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
public Response uninstallExtension(
final @PathParam("extensionId") @ApiParam(value = "extension ID", required = true) String extensionId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.smarthome.extensionservice.marketplace.automation</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ds.core.builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Eclipse SmartHome IoT Marketplace Extension Automation Support
Bundle-SymbolicName: org.eclipse.smarthome.extensionservice.marketplace.automation;singleton:=true
Bundle-Vendor: Eclipse.org/SmartHome
Bundle-Version: 0.9.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ClassPath: .
Import-Package: org.apache.commons.io,
org.eclipse.smarthome.automation.parser,
org.eclipse.smarthome.automation.template,
org.eclipse.smarthome.config.core,
org.eclipse.smarthome.core.common.registry,
org.eclipse.smarthome.core.extension,
org.eclipse.smarthome.core.storage,
org.eclipse.smarthome.extensionservice.marketplace,
org.osgi.framework,
org.slf4j
Bundle-ActivationPolicy: lazy
Service-Component: OSGI-INF/*.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.eclipse.smarthome.extensionservice.marketplace.automation">
<implementation class="org.eclipse.smarthome.extensionservice.marketplace.automation.internal.AutomationExtensionHandler"/>
<reference bind="setMarketplaceRuleTemplateProvider" cardinality="1..1" interface="org.eclipse.smarthome.extensionservice.marketplace.automation.internal.MarketplaceRuleTemplateProvider" name="MarketplaceRuleTemplateProvider" policy="static" unbind="unsetMarketplaceRuleTemplateProvider"/>
<service>
<provide interface="org.eclipse.smarthome.extensionservice.marketplace.MarketplaceExtensionHandler"/>
</service>
</scr:component>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.eclipse.smarthome.extensionservice.marketplace">
<implementation class="org.eclipse.smarthome.extensionservice.marketplace.automation.internal.MarketplaceRuleTemplateProvider"/>
<service>
<provide interface="org.eclipse.smarthome.extensionservice.marketplace.automation.internal.MarketplaceRuleTemplateProvider"/>
<provide interface="org.eclipse.smarthome.automation.template.RuleTemplateProvider"/>
</service>
<reference bind="setStorageService" cardinality="1..1" interface="org.eclipse.smarthome.core.storage.StorageService" name="StorageService" policy="static" unbind="unsetStorageService"/>
<reference bind="setParser" cardinality="1..1" interface="org.eclipse.smarthome.automation.parser.Parser" name="Parser" policy="static" target="(&amp;(format=json)(parser.type=parser.template))" unbind="unsetParser"/>
</scr:component>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>

<p>&lt;<em>May 12, 2015</em>&gt;</p>
<h3>License</h3>

<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>

<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>

</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
output.. = target/classes
bin.includes = META-INF/,\
.,\
OSGI-INF/,\
about.html
source.. = src/main/java/
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.eclipse.smarthome.extensionservice</groupId>
<artifactId>pom</artifactId>
<version>0.9.0-SNAPSHOT</version>
</parent>

<artifactId>org.eclipse.smarthome.extensionservice.marketplace.automation</artifactId>
<packaging>eclipse-plugin</packaging>

<name>Eclipse SmartHome IoT Marketplace Extension Automation Support</name>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.extensionservice.marketplace.automation.internal;

import java.io.IOException;
import java.net.URL;

import org.apache.commons.io.IOUtils;
import org.eclipse.smarthome.automation.template.RuleTemplateProvider;
import org.eclipse.smarthome.core.storage.Storage;
import org.eclipse.smarthome.extensionservice.marketplace.MarketplaceExtension;
import org.eclipse.smarthome.extensionservice.marketplace.MarketplaceExtensionHandler;
import org.eclipse.smarthome.extensionservice.marketplace.MarketplaceHandlerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A {@link MarketplaceExtensionHandler} implementation, which handles rule templates as JSON files and installs
* them by adding them to a {@link Storage}. The templates are then served from this storage through a dedicated
* {@link RuleTemplateProvider}.
*
* @author Kai Kreuzer - Initial contribution and API
*
*/
public class AutomationExtensionHandler implements MarketplaceExtensionHandler {

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

private MarketplaceRuleTemplateProvider marketplaceRuleTemplateProvider;

protected void setMarketplaceRuleTemplateProvider(MarketplaceRuleTemplateProvider marketplaceRuleTemplateProvider) {
this.marketplaceRuleTemplateProvider = marketplaceRuleTemplateProvider;
}

protected void unsetMarketplaceRuleTemplateProvider(
MarketplaceRuleTemplateProvider marketplaceRuleTemplateProvider) {
this.marketplaceRuleTemplateProvider = null;
}

@Override
public boolean supports(MarketplaceExtension ext) {
// we support only rule templates in JSON format so far
return ext.getType().equals(MarketplaceExtension.EXT_TYPE_RULE_TEMPLATE)
&& ext.getPackageFormat().equals(MarketplaceExtension.EXT_FORMAT_JSON);
}

@Override
public boolean isInstalled(MarketplaceExtension ext) {
return marketplaceRuleTemplateProvider.get(ext.getId()) != null;
}

@Override
public void install(MarketplaceExtension ext) throws MarketplaceHandlerException {
String url = ext.getDownloadUrl();
try {
String template = getTemplate(url);
marketplaceRuleTemplateProvider.addTemplateAsJSON(ext.getId(), template);
} catch (IOException e) {
logger.error("Rule template from marketplace cannot be downloaded: {}", e.getMessage());
throw new MarketplaceHandlerException("Template cannot be downloaded.");
} catch (Exception e) {
logger.error("Rule template from marketplace is invalid: {}", e.getMessage());
throw new MarketplaceHandlerException("Template is not valid.");
}
}

@Override
public void uninstall(MarketplaceExtension ext) throws MarketplaceHandlerException {
marketplaceRuleTemplateProvider.remove(ext.getId());
}

private String getTemplate(String urlString) throws IOException {
URL url = new URL(urlString);
return IOUtils.toString(url);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.extensionservice.marketplace.automation.internal;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Locale;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.eclipse.smarthome.automation.parser.Parser;
import org.eclipse.smarthome.automation.parser.ParsingException;
import org.eclipse.smarthome.automation.template.RuleTemplate;
import org.eclipse.smarthome.automation.template.RuleTemplateProvider;
import org.eclipse.smarthome.core.common.registry.DefaultAbstractManagedProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This class provides local access to the market place content. Once started, it downloads the catalog and then makes
* its content available from memory.
*
* Note that there is no progressive/lazy browsing implemented yet, but the service downloads the whole catalog.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this comment this correct?
This file does not download anything, does it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Moved to MarketplaceProxy, correct.
Change comment please

* Once the marketplace is filled with a lot of content, this will need to be addressed.
*
* @author Kai Kreuzer - Initial contribution and API
*
*/
public class MarketplaceRuleTemplateProvider extends DefaultAbstractManagedProvider<RuleTemplate, String>
implements RuleTemplateProvider {

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

private Parser<RuleTemplate> parser;

@Override
public RuleTemplate getTemplate(String uid, Locale locale) {
return get(uid);
}

@Override
public Collection<RuleTemplate> getTemplates(Locale locale) {
return getAll();
}

@Override
protected String getKey(RuleTemplate element) {
return element.getUID();
}

@Override
protected String getStorageName() {
return "org.eclipse.smarthome.extensionservice.marketplace.RuleTemplates";
}

@Override
protected String keyToString(String key) {
return key;
}

protected void setParser(Parser<RuleTemplate> parser) {
this.parser = parser;
}

protected void unsetParser(Parser<RuleTemplate> parser) {
this.parser = null;
}

/**
* This adds a new rule template to the persistent storage.
*
* @param uid the UID to be used for the template
* @param json the template content as a json string
*
* @throws ParsingException if the content cannot be parsed correctly
*/
public void addTemplateAsJSON(String uid, String json) throws ParsingException {
try (InputStreamReader isr = new InputStreamReader(IOUtils.toInputStream(json))) {
Set<RuleTemplate> templates = parser.parse(isr);
if (templates.size() != 1) {
throw new IllegalArgumentException("JSON must contain exactly one template!");
} else {
RuleTemplate entry = templates.iterator().next();
RuleTemplate template = new RuleTemplate(uid, entry.getLabel(), entry.getDescription(), entry.getTags(),
entry.getTriggers(), entry.getConditions(), entry.getActions(),
entry.getConfigurationDescriptions(), entry.getVisibility());
add(template);
}
} catch (IOException e) {
logger.error("Cannot close input stream.", e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.smarthome.extensionservice.marketplace</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ds.core.builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8
Loading