Author: mnuttall
Date: Tue Oct 9 08:47:01 2012
New Revision: 1395912
URL: http://svn.apache.org/viewvc?rev=1395912&view=rev
Log:
Aries-929: install subsystems from IDirectory objects - from a patch by
Amardeep Bhattal
Added:
aries/trunk/util/util-r42/src/main/java/org/apache/aries/util/filesystem/IDirectoryFinder.java
Modified:
aries/trunk/subsystem/subsystem-core/pom.xml
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Location.java
aries/trunk/subsystem/subsystem-itests/pom.xml
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/BlueprintTest.java
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/HelloWorldTest.java
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java
Modified: aries/trunk/subsystem/subsystem-core/pom.xml
URL:
http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/pom.xml?rev=1395912&r1=1395911&r2=1395912&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/pom.xml (original)
+++ aries/trunk/subsystem/subsystem-core/pom.xml Tue Oct 9 08:47:01 2012
@@ -68,7 +68,7 @@
<dependency>
<groupId>org.apache.aries</groupId>
<artifactId>org.apache.aries.util</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.osgi</groupId>
Modified:
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
URL:
http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java?rev=1395912&r1=1395911&r2=1395912&view=diff
==============================================================================
---
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
(original)
+++
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
Tue Oct 9 08:47:01 2012
@@ -23,6 +23,7 @@ import java.util.HashSet;
import java.util.Hashtable;
import org.apache.aries.application.modelling.ModelledResourceManager;
+import org.apache.aries.util.filesystem.IDirectoryFinder;
import org.eclipse.equinox.region.RegionDigraph;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
@@ -77,6 +78,7 @@ public class Activator implements Bundle
private final Collection<ServiceRegistration<?>> registrations = new
HashSet<ServiceRegistration<?>>();
private final Collection<Repository> repositories =
Collections.synchronizedSet(new HashSet<Repository>());
+ private final Collection<IDirectoryFinder> finders =
Collections.synchronizedSet(new HashSet<IDirectoryFinder>());
public BundleContext getBundleContext() {
return bundleContext;
@@ -98,6 +100,10 @@ public class Activator implements Bundle
return Collections.unmodifiableCollection(repositories);
}
+ public Collection<IDirectoryFinder> getIDirectoryFinders() {
+ return Collections.unmodifiableCollection(finders);
+ }
+
public Resolver getResolver() {
return resolver;
}
@@ -202,9 +208,11 @@ public class Activator implements Bundle
.append(org.osgi.framework.Constants.OBJECTCLASS).append('=')
.append(Resolver.class.getName()).append(")(")
.append(org.osgi.framework.Constants.OBJECTCLASS).append('=')
- .append(Repository.class.getName()).append(")(")
+ .append(Repository.class.getName()).append(")(")
.append(org.osgi.framework.Constants.OBJECTCLASS).append('=')
-
.append(ModelledResourceManager.class.getName()).append("))").toString();
+ .append(ModelledResourceManager.class.getName()).append(")(")
+ .append(org.osgi.framework.Constants.OBJECTCLASS).append('=')
+ .append(IDirectoryFinder.class.getName()).append("))").toString();
}
private boolean hasRequiredServices() {
@@ -255,6 +263,8 @@ public class Activator implements Bundle
activate();
}
}
+ else if (service instanceof IDirectoryFinder)
+ finders.add((IDirectoryFinder)service);
else
repositories.add((Repository)service);
return service;
@@ -299,6 +309,8 @@ public class Activator implements Bundle
this.modelledResourceManager =
modelledResourceManager;
}
}
+ else if (service instanceof IDirectoryFinder)
+ finders.remove(service);
else
repositories.remove(service);
}
Modified:
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Location.java
URL:
http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Location.java?rev=1395912&r1=1395911&r2=1395912&view=diff
==============================================================================
---
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Location.java
(original)
+++
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Location.java
Tue Oct 9 08:47:01 2012
@@ -13,44 +13,110 @@
*/
package org.apache.aries.subsystem.core.internal;
+
+import static org.apache.aries.util.filesystem.IDirectoryFinder.IDIR_SCHEME;
+
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
+import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.util.Collection;
import org.apache.aries.util.filesystem.FileSystem;
import org.apache.aries.util.filesystem.IDirectory;
+import org.apache.aries.util.filesystem.IDirectoryFinder;
import org.osgi.framework.Version;
public class Location {
- private final SubsystemUri uri;
- private final String value;
-
- public Location(String location) throws MalformedURLException,
URISyntaxException {
- value = location;
- if (location.startsWith("subsystem://"))
- uri = new SubsystemUri(location);
- else
- uri = null;
- }
-
- public String getSymbolicName() {
- return uri == null ? null : uri.getSymbolicName();
- }
-
- public String getValue() {
- return value;
- }
-
- public Version getVersion() {
- return uri == null ? null : uri.getVersion();
- }
-
- public IDirectory open() throws IOException, URISyntaxException {
- URL url = uri == null ? new URL(value) : uri.getURL();
- if ("file".equals(url.getProtocol()))
- return FileSystem.getFSRoot(new File(url.toURI()));
- return FileSystem.getFSRoot(url.openStream());
- }
+ enum LocationType {
+ SUBSYSTEM("subsystem", "subsystem"), IDIRFINDER(IDIR_SCHEME, IDIR_SCHEME),
URL("url", null);
+ final String toString;
+ final String scheme;
+ LocationType(String toString, String scheme) {this.toString = toString;
this.scheme = scheme;}
+ public String toString() {return toString;}
+ };
+
+ private final LocationType type;
+ private final String value;
+ private final URI uri;
+ private final URL url;
+ private final SubsystemUri subsystemUri;
+
+ /*
+ * type, value, uri are always set to some non-null value, url and
+ * subsystemUri depend on the type.
+ */
+ public Location(String location) throws MalformedURLException,
URISyntaxException {
+ value = location;
+ URI locationUri = new URI(location);
+ if (locationUri.isAbsolute()) { // i.e. looks like scheme:something
+ String scheme = locationUri.getScheme();
+ if (LocationType.SUBSYSTEM.scheme.equals(scheme)) {
+ type = LocationType.SUBSYSTEM;
+ subsystemUri = new SubsystemUri(location);
+ url = subsystemUri.getURL(); // subsystem uris may contain a nested
url.
+ uri = (url==null) ? null : url.toURI();
+ } else if (LocationType.IDIRFINDER.scheme.equals(scheme)) {
+ type = LocationType.IDIRFINDER;
+ subsystemUri = null;
+ url = null;
+ uri = locationUri;
+ } else { // otherwise will only accept a url, (a
url
+ type = LocationType.URL; // always has a scheme, so fine to have
+ subsystemUri = null; // this inside the 'if isAbsolute' block).
+ url = locationUri.toURL();
+ uri = locationUri;
+ }
+ } else {
+ throw new IllegalArgumentException(location + " is not an absolute uri");
+ }
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public String getSymbolicName() {
+ return (type==LocationType.SUBSYSTEM) ? subsystemUri.getSymbolicName() :
null;
+ }
+
+ public Version getVersion() {
+ return (type==LocationType.SUBSYSTEM) ? subsystemUri.getVersion() : null;
+ }
+
+ public IDirectory open() throws IOException, URISyntaxException {
+ switch (type) {
+ case IDIRFINDER :
+ return retrieveIDirectory();
+ case SUBSYSTEM : // drop through to share 'case url' code
+ case URL :
+ if ("file".equals(url.getProtocol()))
+ return FileSystem.getFSRoot(new File(uri));
+ else
+ return FileSystem.getFSRoot(url.openStream());
+ default : // should never get here as switch should cover all types
+ throw new UnsupportedOperationException("cannot open location of type
" + type);
+ }
+ }
+
+ /*
+ * Although the uri should contain information about the directory finder
+ * service to use to retrieve the directory, there are not expected to be
+ * many such services in use (typically one), so a simple list of all
+ * directory finders is maintained by the activator and we loop over them in
+ * turn until the desired directory is retrieved or there are no more finders
+ * left to call.
+ */
+ private IDirectory retrieveIDirectory() throws IOException {
+ Collection<IDirectoryFinder> iDirectoryFinders =
Activator.getInstance().getIDirectoryFinders();
+ for(IDirectoryFinder iDirectoryFinder : iDirectoryFinders) {
+ IDirectory directory = iDirectoryFinder.retrieveIDirectory(uri);
+ if (directory!=null)
+ return directory;
+ }
+ throw new IOException("cannot find IDirectory corresponding to id " + uri);
+ }
+
}
\ No newline at end of file
Modified: aries/trunk/subsystem/subsystem-itests/pom.xml
URL:
http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/pom.xml?rev=1395912&r1=1395911&r2=1395912&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/pom.xml (original)
+++ aries/trunk/subsystem/subsystem-itests/pom.xml Tue Oct 9 08:47:01 2012
@@ -37,7 +37,7 @@
<groupId>org.apache.aries</groupId>
<artifactId>org.apache.aries.util</artifactId>
<scope>test</scope>
- <version>1.0.0</version>
+ <version>1.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.osgi</groupId>
@@ -80,7 +80,7 @@
</exclusion>
</exclusions>
</dependency>
- <dependency>
+ <dependency>
<groupId>org.apache.aries.blueprint</groupId>
<artifactId>org.apache.aries.blueprint</artifactId>
<version>1.0.0</version>
Modified:
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/BlueprintTest.java
URL:
http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/BlueprintTest.java?rev=1395912&r1=1395911&r2=1395912&view=diff
==============================================================================
---
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/BlueprintTest.java
(original)
+++
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/BlueprintTest.java
Tue Oct 9 08:47:01 2012
@@ -1,75 +1,61 @@
-package org.apache.aries.subsystem.itests;
-
-import static org.apache.aries.itest.ExtraOptions.mavenBundle;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.OptionUtils.combine;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.apache.aries.subsystem.itests.hello.api.Hello;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.Configuration;
-import org.ops4j.pax.exam.junit.JUnit4TestRunner;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.framework.hooks.weaving.WeavingHook;
-import org.osgi.framework.hooks.weaving.WovenClass;
-import org.osgi.service.subsystem.Subsystem;
-import org.osgi.service.subsystem.SubsystemException;
-
-/*
- * iTest for blueprint with subsystems
- */
-@RunWith(JUnit4TestRunner.class)
-public class BlueprintTest extends SubsystemTest
-{
- private static boolean _testAppCreated = false;
-
- @Before
- public void setUp() throws Exception
- {
- super.setUp();
- if (!_testAppCreated) {
- createApplication("blueprint", new
String[]{"blueprint.jar"});
- _testAppCreated = true;
- }
- }
-
- @Test
- public void checkBlueprint() throws Exception
- {
- Subsystem subsystem = installSubsystemFromFile
("blueprint.esa");
- try {
- startSubsystem(subsystem);
- BundleContext bc = subsystem.getBundleContext();
- Hello h = getOsgiService(bc, Hello.class, null,
DEFAULT_TIMEOUT);
- String message = h.saySomething();
- assertEquals("Wrong message back",
"messageFromBlueprint", message);
- } finally {
- stopSubsystem(subsystem);
- uninstallSubsystem(subsystem);
- }
- }
-
- @Configuration
- public static Option[] extraBundles()
- {
- return options(
- mavenBundle("org.apache.aries.subsystem",
"org.apache.aries.subsystem.itest.interfaces"),
- mavenBundle("org.apache.aries",
"org.apache.aries.util"),
- mavenBundle("org.apache.aries.blueprint",
"org.apache.aries.blueprint"),
- mavenBundle("org.ow2.asm", "asm-all"),
- mavenBundle("org.apache.aries.proxy",
"org.apache.aries.proxy")
-//
org.ops4j.pax.exam.container.def.PaxRunnerOptions.vmOption("-Xdebug
-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=7777")
- );
- }
-}
+package org.apache.aries.subsystem.itests;
+
+import static org.junit.Assert.assertEquals;
+import static org.ops4j.pax.exam.CoreOptions.options;
+
+import org.apache.aries.subsystem.itests.hello.api.Hello;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.subsystem.Subsystem;
+
+/*
+ * iTest for blueprint with subsystems
+ */
+@RunWith(JUnit4TestRunner.class)
+public class BlueprintTest extends SubsystemTest
+{
+ private static boolean _testAppCreated = false;
+
+ @Before
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ if (!_testAppCreated) {
+ createApplication("blueprint", new
String[]{"blueprint.jar"});
+ _testAppCreated = true;
+ }
+ }
+
+ @Test
+ public void checkBlueprint() throws Exception
+ {
+ Subsystem subsystem = installSubsystemFromFile
("blueprint.esa");
+ try {
+ startSubsystem(subsystem);
+ BundleContext bc = subsystem.getBundleContext();
+ Hello h = getOsgiService(bc, Hello.class, null,
DEFAULT_TIMEOUT);
+ String message = h.saySomething();
+ assertEquals("Wrong message back",
"messageFromBlueprint", message);
+ } finally {
+ stopSubsystem(subsystem);
+ uninstallSubsystem(subsystem);
+ }
+ }
+
+ @Configuration
+ public static Option[] extraBundles()
+ {
+ return options(
+ mavenBundle("org.apache.aries.subsystem",
"org.apache.aries.subsystem.itest.interfaces"),
+ mavenBundle("org.apache.aries.blueprint",
"org.apache.aries.blueprint"),
+ mavenBundle("org.ow2.asm", "asm-all"),
+ mavenBundle("org.apache.aries.proxy",
"org.apache.aries.proxy")
+//
org.ops4j.pax.exam.container.def.PaxRunnerOptions.vmOption("-Xdebug
-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=7777")
+ );
+ }
+}
Modified:
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/HelloWorldTest.java
URL:
http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/HelloWorldTest.java?rev=1395912&r1=1395911&r2=1395912&view=diff
==============================================================================
---
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/HelloWorldTest.java
(original)
+++
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/HelloWorldTest.java
Tue Oct 9 08:47:01 2012
@@ -1,55 +1,121 @@
-package org.apache.aries.subsystem.itests;
-
-import static org.junit.Assert.assertEquals;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.OptionUtils.combine;
-
-import org.apache.aries.subsystem.itests.hello.api.Hello;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.JUnit4TestRunner;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.subsystem.Subsystem;
-
-@RunWith(JUnit4TestRunner.class)
-public class HelloWorldTest extends SubsystemTest
-{
- private static boolean _testAppCreated = false;
-
- @Before
- public void installTestApp() throws Exception
- {
- if (!_testAppCreated) {
- createApplication("hello", new
String[]{"helloImpl.jar"});
- _testAppCreated = true;
- }
- }
-
- @Test
- public void testHello() throws Exception
- {
- Subsystem subsystem = installSubsystemFromFile("hello.esa");
- try {
- subsystem.start();
- BundleContext bc = subsystem.getBundleContext();
- Hello h = getOsgiService(bc, Hello.class, null,
DEFAULT_TIMEOUT);
- String message = h.saySomething();
- assertEquals ("Wrong message back", "something",
message);
- subsystem.stop();
- }
- finally {
- uninstallSubsystemSilently(subsystem);
- }
- }
-
- protected static Option[] updateOptions(Option[] options)
- {
- Option[] helloOptions = options(
- mavenBundle("org.apache.aries.subsystem",
"org.apache.aries.subsystem.itest.interfaces")
-//
org.ops4j.pax.exam.container.def.PaxRunnerOptions.vmOption("-Xdebug
-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
- );
- return combine(helloOptions, options);
- }
-}
+package org.apache.aries.subsystem.itests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.net.URI;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.aries.subsystem.itests.hello.api.Hello;
+import org.apache.aries.util.filesystem.FileSystem;
+import org.apache.aries.util.filesystem.IDirectory;
+import org.apache.aries.util.filesystem.IDirectoryFinder;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Inject;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.subsystem.Subsystem;
+import org.osgi.service.subsystem.SubsystemException;
+
+@RunWith(JUnit4TestRunner.class)
+public class HelloWorldTest extends SubsystemTest
+{
+ // Get the root subsystem bundle context.
+ @Inject
+ protected BundleContext bundleContext;
+
+ private static boolean _testAppCreated = false;
+
+ /*
+ * An implementation of the IDirectoryFinder interface that provides the
+ * IDirectory that corresponds to some id URI. In practice this could
come
+ * from anywhere (exploded archive on filesystem, in-memory, IDE etc)
but
+ * for the test just use an archive file.
+ */
+ static class TestIDirectoryFinder implements IDirectoryFinder {
+ static final String IDIR_FINDERID_VALUE = "TestIDirectoryFinder";
+ static final String IDIR_DIRECTORYID_VALUE = "hello.esa";
+ static final URI HELLO_ID_URI =
+ URI.create(IDIR_SCHEME + "://?" + IDIR_FINDERID_KEY + "=" +
IDIR_FINDERID_VALUE
+ + "&" + IDIR_DIRECTORYID_KEY + "=" + IDIR_DIRECTORYID_VALUE);
+ static final String HELLO_ID_STRING = HELLO_ID_URI.toString();
+
+ public IDirectory retrieveIDirectory(URI idirectoryId) {
+ if (HELLO_ID_URI.equals(idirectoryId)) {
+ File helloEsaFile = new File("hello.esa");
+ IDirectory helloEsaIDir = FileSystem.getFSRoot(helloEsaFile);
+ return helloEsaIDir;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ @Before
+ public void installTestApp() throws Exception
+ {
+ if (!_testAppCreated) {
+ createApplication("hello", new
String[]{"helloImpl.jar"});
+ _testAppCreated = true;
+ }
+ }
+
+ void checkHelloSubsystem(Subsystem helloSubsystem) throws Exception
+ {
+ helloSubsystem.start();
+ BundleContext bc = helloSubsystem.getBundleContext();
+ Hello h = getOsgiService(bc, Hello.class, null, DEFAULT_TIMEOUT);
+ String message = h.saySomething();
+ assertEquals ("Wrong message back", "something", message);
+ helloSubsystem.stop();
+ }
+
+ @Test
+ public void testHelloFromFile() throws Exception
+ {
+ Subsystem subsystem = installSubsystemFromFile("hello.esa");
+ try {
+ checkHelloSubsystem(subsystem);
+ } finally {
+ uninstallSubsystemSilently(subsystem);
+ }
+ }
+
+ @Test
+ public void testHelloFromIDirectory() throws Exception
+ {
+ // Sanity check, application should not install if no IDirectoryFinder
+ // services are registered, which should be the case on entry to this test.
+ try {
+ installSubsystem(getRootSubsystem(),
TestIDirectoryFinder.HELLO_ID_STRING, null);
+ fail("installed esa application from idir without an idirfinder service,
shouldn't be possible.");
+ } catch (SubsystemException se) {
+ // expected exception
+ }
+
+ // The root subsystem already exists and has a service tracker for
+ // IDirectoryFinder services, so it will be notified on service
registration.
+ Dictionary<String, String> properties = new Hashtable<String, String>();
+ properties.put(IDirectoryFinder.IDIR_FINDERID_KEY,
TestIDirectoryFinder.IDIR_FINDERID_VALUE);
+ ServiceRegistration<IDirectoryFinder> serviceRegistration =
+ bundleContext.registerService(IDirectoryFinder.class, new
TestIDirectoryFinder(), properties);
+
+ // Call the SubsystemTest.installSubsystem method that does not create a
URL
+ // and stream from the location, as we just need the location string
passed
+ // through to the installing root subsystem.
+ Subsystem subsystem = installSubsystem(getRootSubsystem(),
TestIDirectoryFinder.HELLO_ID_STRING, null);
+ try {
+ checkHelloSubsystem(subsystem);
+ } finally {
+ uninstallSubsystemSilently(subsystem);
+ if (serviceRegistration!=null)
+ serviceRegistration.unregister();
+ }
+ }
+
+}