-
Notifications
You must be signed in to change notification settings - Fork 779
Initial contribution of an IoT Market extension service #3076
Conversation
I assume the file |
d5a416a
to
24e9601
Compare
thx, removed it. |
OSGI-INF/,\ | ||
about.html,\ | ||
OSGI-INF/MarketplaceExtensionService.xml,\ | ||
OSGI-INF/MarketplaceTemplateProvider.xml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The two lines above could be removed, the whole directory is already included.
<artifactId>org.eclipse.smarthome.extensionservice.marketplace</artifactId> | ||
<packaging>eclipse-plugin</packaging> | ||
|
||
<name>Eclipse SmartHome Web Audio Support</name> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect another name 😉
} | ||
|
||
// we mark it as volatile, so that it isn't serialized through GSON | ||
private volatile String downloadUrl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't transient the correct keyword to disable serialization?
} | ||
break; | ||
default: | ||
postFailureEvent(extensionId, "Id not known."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A break (also for the last statement) would be nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In uninstall
you return, so no post(Un)installedEvent is called. Do you want to call return
here, too?
@maggu2810 Code has not been cleaned up yet, I mainly pushed it as WIP for testing the new Paper UI features. But thanks anyway, I'll incorporate your feedback (and will let you know once the PR is really ready for review :-)) |
737f3f8
to
446abee
Compare
@maggu2810 Ready for review now - it is still a basic implementation that only covers certain use cases, but I think it is a good starting point. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been just a first reading of the code, need to check it out later and start a detailed review.
Manifest-Version: 1.0 | ||
Bundle-ManifestVersion: 2 | ||
Bundle-Name: Eclipse SmartHome IoT Marketplace Extension Service | ||
Bundle-SymbolicName: org.eclipse.smarthome.extensionservice.marketplace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we allow different version in the same runtime or only one (singleton:=true
)?
I assume we didn't look at this attribute most of the time, but I assume we should consider what we want to support.
As long as we do not use version constraints, we should perhaps use singleton plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, we should make sure to use the singleton flag
} | ||
|
||
// we mark it as transient, so that it isn't serialized through GSON | ||
private transient String downloadUrl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO member variables should be placed above the constructor.
@Override | ||
public void uninstall(String extensionId) { | ||
Extension ext = getExtension(extensionId, null); | ||
if (ext != null && ext.isInstalled()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Above you checked for MarketplaceExtension
, do we want to ensure a correct extensionId
here to?
If it is not a MarketplaceExtension (also above) should this be ignored silently or should we throw an IllegalArgumentException
or another one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or perhaps post an failureEvent...
uninstallBinding(extensionId); | ||
break; | ||
default: | ||
postFailureEvent(extensionId, "Id not known."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type is not known, if the ID is not known, we don't step into this place at all.
installBinding(extensionId, mpExt); | ||
break; | ||
default: | ||
postFailureEvent(extensionId, "Id not known."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type is not known, if the ID is not known, we don't step into this place at all.
if (ext instanceof MarketplaceExtension && !ext.isInstalled()) { | ||
MarketplaceExtension mpExt = (MarketplaceExtension) ext; | ||
String type = getType(extensionId); | ||
switch (type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this a potential NPE as getType may return null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch
String[] parts = line.split(";"); | ||
try { | ||
map.put(parts[0], Long.valueOf(parts[1])); | ||
} catch (Exception e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should check for parts.length >= 2
before instead of execute the code and catch exceptions.
So, the only thing to catch is the NumberFormatException.
this.parser = parser; | ||
} | ||
|
||
protected void unseteParser(Parser<RuleTemplate> parser) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unset without an "e" at the end
* The category of the marketplace | ||
*/ | ||
public Category[] categories; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a new line at the end of the file.
Without the new line this will lead in noisy diffs in Git (and some quality tools also prefer new lines).
We should change the IDE to do it for us.
public String packageformat; | ||
|
||
public String updateurl; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a new line at the end of the file.
Without the new line this will lead in noisy diffs in Git (and some quality tools also prefer new lines).
We should change the IDE to do it for us.
Signed-off-by: Kai Kreuzer <kai@openhab.org>
Signed-off-by: Kai Kreuzer <kai@openhab.org>
updated |
Signed-off-by: Kai Kreuzer <kai@openhab.org>
Please refrain from a final review for the moment - I just noticed that I need some refactoring to also make it possible to use this extension service, if no automation component is installed... |
Ah, okay. |
…late) support to a separate bundle Signed-off-by: Kai Kreuzer <kai@openhab.org>
Signed-off-by: Kai Kreuzer <kai@openhab.org>
Ping! |
<bundle>mvn:org.eclipse.smarthome.extensionservice/org.eclipse.smarthome.extensionservice.marketplace/${project.version}</bundle> | ||
</feature> | ||
|
||
<feature name="esh-extensionservice-marketplace-automation" version="${project.version}"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the feature verification complete?
Shouldn't marketplace-automation depend on the marketplace feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not have feature validation in place at ESH. You are right, it should depend on the marketplace feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated. Any further review comments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not have feature validation in place at ESH.
You are wrong!
It has been present from the beginning.
commit 8484160501a8eb8fc62f84eef82b44bbf2050877
Date: Mon Apr 18 10:24:48 2016 +0200
Yourself moved it from features/karaf-verify
to features/karaf/verify
at the beginning of 2017.
Perhaps you remember that we talked on introduction of the Karaf feature if the verifiction should be enabled at build time to be executed automatically or only be in place to be triggered manually.
It's just about the line <!--<phase>process-resources</phase>-->
in the POM file, if we bind the goal to a phase or not.
To trigger the verification manually, you can do it as usual using this command:
mvn -pl features/karaf/verify org.apache.karaf.tooling:karaf-maven-plugin:verify@verify-esh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated. Any further review comments?
Haven't had any time for review, just looked at the features yesterday.
Will try to start a review soon, but it's a matter of spare time...
Signed-off-by: Kai Kreuzer <kai@openhab.org>
* 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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
* them through the standard OSGi bundle installation mechanism. | ||
* The information, which installed bundle corresponds to which extension is written to a file in the bundle's data | ||
* store. It is therefore wiped together with the bundles upon an OSGi "clean". | ||
* We might want to move this class into a separate bundle in future, when we add support for further extension types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be already a good time as we have a different one for the automation one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If ok for you, I would do that as a follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay for me if the "follow up PR" is following 😉
* multiple handers support it, it is undefined which one will be called. | ||
* This mechanism allows solutions to add support for specific formats (e.g. Karaf features) that are not supported by | ||
* ESH out of the box. | ||
* It also allows to decide which extension types are made available at all. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As there is only one handler allowed per type+format and every solution is allowed to add its own type+format handlers, shouldn't the type and format be defined by the handler itself instead adding global constants to the MarketplaceExtension
?
So, moving
EXT_TYPE_BINDING
andEXT_FORMAT_BUNDLE
toBindingExtensionHandler
EXT_TYPE_RULE_TEMPLATE
andEXT_FORMAT_JSON
toAutomationExtensionHandler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, okay, see the usage below...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The types are statically defined in the IoT marketplace - so if the marketplace is extended, we should also maintain the new types here at a central place as constants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO we should move the bundle market place handler to a separate binding as it has been done for the automation ones.
Some minor comments.
I assume you already tested that the code is working and I don't need to test it myself.
private void postFailureEvent(String extensionId, String msg) { | ||
Event event = ExtensionEventFactory.createExtensionFailureEvent(extensionId, msg); | ||
eventPublisher.post(event); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty line can be removed
default: | ||
return null; | ||
} | ||
sb.append(node.id.replaceAll("[^a-zA-Z0-9_]", "")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the extension ID defined this way (REST): [a-zA-Z_0-9-:]*
You added a colon (:
) above but here you remove colons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are adding the "marketplace:" prefix for the extension ids and hence the part AFTER that prefix should not contain any additional colons. What is converted here is the node id and this is (from what I have seen so far) always a numerical number anyhow, so this line is only a safeguard for the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are adding the "marketplace:" prefix for the extension ids and hence the part AFTER that prefix should not contain any additional colons.
Ah, okay.
* 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. |
There was a problem hiding this comment.
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
public MarketplaceProxy() { | ||
try { | ||
url = new URL(MP_URL); | ||
ThreadPoolManager.getScheduledPool("marketplace").scheduleWithFixedDelay(() -> refresh(), 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At which place is that pool cleaned up again?
getScheduledPool(...)
creates a new if it is not known and put it to a map.
I would expect the MarketProxy should remove ti is it is removed from the system.
But this seems to be a general problem in the ThreadPoolManager
, isn't it?
It adds new Pools to its map and never cleans it up. Miss I something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right - I definitely missed to cancel the scheduled job.
And as we do not need a thread pool but only a single executor, I am not using ThreadPoolManager anymore now.
We can now install and uninstall a bundle. |
Signed-off-by: Kai Kreuzer <kai@openhab.org>
Normally, the bindings will start by themselve as they have "activate immediately" DS components. @maggu2810 I have pushed my changes, I hope this is ok now. Would be happy to have it merged soon to have an initial version to start testing. The market will only launch officially by the end of March, so we can improve things that come up by follow up PRs. |
Signed-off-by: Kai Kreuzer <kai@openhab.org>
Signed-off-by: Kai Kreuzer <kai@openhab.org>
Really? Do you think about a lazy activation, that result in a bundle start if the DS inspect the services? Would be great, if you could give me further details. |
try { | ||
url = new URL(MP_URL); | ||
this.refreshJob = Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(() -> refresh(), 0, | ||
refresh_interval, TimeUnit.SECONDS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC you should call shutdown after you added the job (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdown()).
If you don't use it, the executor does not "know" about, that it does not accept any further jobs.
final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
this.refreshJob = executor.scheduleWithFixedDelay(() -> refresh(), 0, refresh_interval, TimeUnit.SECONDS);
executor.shutdown();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, just pushed a commit to properly shut it down
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One minor comment about the executor shutdown.
If you change it or you explain me that it is really not necessary (because stuff is broken doing so), I approve this PR.
if you need it today, you can merge it after the fix yourself (I agree).
* them through the standard OSGi bundle installation mechanism. | ||
* The information, which installed bundle corresponds to which extension is written to a file in the bundle's data | ||
* store. It is therefore wiped together with the bundles upon an OSGi "clean". | ||
* We might want to move this class into a separate bundle in future, when we add support for further extension types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay for me if the "follow up PR" is following 😉
Yes, that's what I thought about, you are right - anyhow, I have changed the code to always do a bundle start. |
Signed-off-by: Kai Kreuzer <kai@openhab.org>
Yes, I will have to, because I actually plan a different implementation on openHAB side later, which will use felix fileinstall instead of directly installing the bundles. So no risk that this follow-up PR is forgotten :-) |
* master: (483 commits) improve cron expression tests (eclipse-archived#3133) Fix eclipse-archived#3132 (eclipse-archived#3134) Display of image items in classic UI and basic UI (eclipse-archived#3055) Implemented tests for org.eclipse.smarthome.core.audio (eclipse-archived#2687) Changes in org.eclipse.smarthome.core.audio: (eclipse-archived#3119) Fix RuleEnablementHandler name (eclipse-archived#3125) run Eclipse formatter rules on Hue binding (eclipse-archived#3123) Bug fix: months shown from 0-11 (eclipse-archived#3124) Hide rule from catalog entry if no rule extensions exist (eclipse-archived#3117) Parsefloat instead if int (eclipse-archived#3118) Move Jekyll preamble to doc build process (out of source files) (eclipse-archived#3116) Initial contribution of an IoT Market extension service (eclipse-archived#3076) Fixes for transformation readmes (eclipse-archived#3111) Eclipse setup: set source 1.8 compliance level (eclipse-archived#3109) Change max / min value types to Object (for better handling of floats) (eclipse-archived#3103) removed not recommended items in lifx README (eclipse-archived#3030) Parameter context docs updated Tycho respect Eclipse settings on Maven build Changed the names of NtpOSGiTest test methods (eclipse-archived#5) NTP binding test: replace Groovy by Java ... # Conflicts: # docs/documentation/development/bindings/xml-reference.md
implements #2924
Signed-off-by: Kai Kreuzer kai@openhab.org