You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2015/09/23 13:32:08 UTC

karaf git commit: [KARAF-3933] Deal with shared bundle between features

Repository: karaf
Updated Branches:
  refs/heads/karaf-3.0.x 34fd7c0a3 -> 06f35ca4a


[KARAF-3933] Deal with shared bundle between features


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/06f35ca4
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/06f35ca4
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/06f35ca4

Branch: refs/heads/karaf-3.0.x
Commit: 06f35ca4ac9b613d4a5f18190ca8b207bfce6ff6
Parents: 34fd7c0
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Wed Sep 23 13:31:30 2015 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Wed Sep 23 13:31:30 2015 +0200

----------------------------------------------------------------------
 .../features/internal/FeaturesServiceImpl.java  | 234 ++++++++++---------
 .../karaf/features/FeaturesServiceTest.java     |   3 +-
 2 files changed, 123 insertions(+), 114 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/06f35ca4/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
index 0c7982b..6693364 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
@@ -98,11 +98,11 @@ public class FeaturesServiceImpl implements FeaturesService {
     private ThreadLocal<Repository> repo = new ThreadLocal<Repository>();
     private EventAdminListener eventAdminListener;
     private String overrides;
-    
+
     public FeaturesServiceImpl(BundleManager bundleManager) {
         this(bundleManager, null);
     }
-    
+
     public FeaturesServiceImpl(BundleManager bundleManager, FeatureConfigInstaller configManager) {
         this.bundleManager = bundleManager;
         this.configManager = configManager;
@@ -120,7 +120,7 @@ public class FeaturesServiceImpl implements FeaturesService {
             }
         }
     }
-    
+
     public long getResolverTimeout() {
         return resolverTimeout;
     }
@@ -172,7 +172,7 @@ public class FeaturesServiceImpl implements FeaturesService {
      * @param uri the features repository URI.
      */
     public void validateRepository(URI uri) throws Exception {
-        
+
         FeatureValidationUtil.validate(uri);
     }
 
@@ -189,7 +189,7 @@ public class FeaturesServiceImpl implements FeaturesService {
     /**
      * Add a features repository.
      *
-     * @param uri the features repository URI.
+     * @param uri     the features repository URI.
      * @param install if true, install all features contained in the features repository.
      * @throws Exception in case of adding failure.
      */
@@ -206,7 +206,7 @@ public class FeaturesServiceImpl implements FeaturesService {
             refreshRepository(uri, install);
         }
     }
-    
+
     /**
      * Refresh a features repository.
      *
@@ -221,7 +221,7 @@ public class FeaturesServiceImpl implements FeaturesService {
     /**
      * Refresh a features repository.
      *
-     * @param uri the features repository URI.
+     * @param uri     the features repository URI.
      * @param install if true, install all features in the features repository.
      * @throws Exception in case of refresh failure.
      */
@@ -251,7 +251,7 @@ public class FeaturesServiceImpl implements FeaturesService {
         callListeners(new RepositoryEvent(repo, RepositoryEvent.EventType.RepositoryAdded, false));
         features = null;
         return repo;
-        
+
     }
 
     /**
@@ -267,7 +267,7 @@ public class FeaturesServiceImpl implements FeaturesService {
     /**
      * Remove a features repository.
      *
-     * @param uri the features repository URI.
+     * @param uri       the features repository URI.
      * @param uninstall if true, uninstall all features from the features repository.
      * @throws Exception in case of remove failure.
      */
@@ -303,8 +303,8 @@ public class FeaturesServiceImpl implements FeaturesService {
      * @throws Exception in case of restore failure.
      */
     public void restoreRepository(URI uri) throws Exception {
-    	repositories.put(uri, repo.get());
-    	callListeners(new RepositoryEvent(repo.get(), RepositoryEvent.EventType.RepositoryAdded, false));
+        repositories.put(uri, repo.get());
+        callListeners(new RepositoryEvent(repo.get(), RepositoryEvent.EventType.RepositoryAdded, false));
         features = null;
     }
 
@@ -318,7 +318,7 @@ public class FeaturesServiceImpl implements FeaturesService {
         Collection<Repository> repos = new ArrayList<Repository>(repositories.values());
         return repos.toArray(new Repository[repos.size()]);
     }
-    
+
     @Override
     public Repository getRepository(String repoName) {
         for (Repository repo : this.repositories.values()) {
@@ -348,13 +348,13 @@ public class FeaturesServiceImpl implements FeaturesService {
      * @throws Exception in case of install failure.
      */
     public void installFeature(String name) throws Exception {
-    	installFeature(name, org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION);
+        installFeature(name, org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION);
     }
 
     /**
      * Install a feature identified by a name, including a set of options.
      *
-     * @param name the name of the feature.
+     * @param name    the name of the feature.
      * @param options the installation options.
      * @throws Exception in case of install failure.
      */
@@ -365,7 +365,7 @@ public class FeaturesServiceImpl implements FeaturesService {
     /**
      * Install a feature identified by a name and a version.
      *
-     * @param name the name of the feature.
+     * @param name    the name of the feature.
      * @param version the version of the feature.
      * @throws Exception in case of install failure.
      */
@@ -376,7 +376,7 @@ public class FeaturesServiceImpl implements FeaturesService {
     /**
      * Install a feature identified by a name and a version, including a set of options.
      *
-     * @param name the name of the feature.
+     * @param name    the name of the feature.
      * @param version the version of the feature.
      * @param options the installation options.
      * @throws Exception in case of install failure.
@@ -421,7 +421,7 @@ public class FeaturesServiceImpl implements FeaturesService {
      * Install a set of features, including a set of options.
      *
      * @param features a set of <code>Feature</code>.
-     * @param options the installation options set.
+     * @param options  the installation options set.
      * @throws Exception in case of install failure.
      */
     public void installFeatures(Set<Feature> features, EnumSet<Option> options) throws Exception {
@@ -432,7 +432,7 @@ public class FeaturesServiceImpl implements FeaturesService {
             // Install everything
             for (Feature f : features) {
                 InstallationState s = new InstallationState();
-            	try {
+                try {
                     doInstallFeature(s, f, verbose);
                     doInstallFeatureConditionals(s, f, verbose);
                     //Check if current feature satisfies the conditionals of existing features
@@ -448,7 +448,7 @@ public class FeaturesServiceImpl implements FeaturesService {
                     state.features.putAll(s.features);
                     state.installed.addAll(s.installed);
                     state.bundleStartLevels.putAll(s.bundleStartLevels);
-            	} catch (Exception e) {
+                } catch (Exception e) {
                     failure.bundles.addAll(s.bundles);
                     failure.features.putAll(s.features);
                     failure.installed.addAll(s.installed);
@@ -457,7 +457,7 @@ public class FeaturesServiceImpl implements FeaturesService {
                     } else {
                         throw e;
                     }
-            	}
+                }
             }
             bundleManager.refreshBundles(state.bundles, state.installed, options);
             // start all bundles sorted by startlvl if wished for
@@ -479,7 +479,7 @@ public class FeaturesServiceImpl implements FeaturesService {
             // Clean up for batch
             if (!options.contains(Option.NoCleanIfFailure)) {
                 failure.installed.removeAll(state.bundles);
-                if (failure.installed.size()>0) {
+                if (failure.installed.size() > 0) {
                     bundleManager.uninstall(failure.installed);
                 }
             }
@@ -500,61 +500,69 @@ public class FeaturesServiceImpl implements FeaturesService {
     /**
      * Start a bundle.
      *
-     * @param state the current bundle installation state.
+     * @param state  the current bundle installation state.
      * @param bundle the bundle to start.
      * @throws Exception in case of start failure.
      */
-	private void startBundle(InstallationState state, Bundle bundle) throws Exception {
-		if (!isFragment(bundle)) {
-		    // do not start bundles that are persistently stopped
-		    if (state.installed.contains(bundle)
-		            || (bundle.getState() != Bundle.STARTING && bundle.getState() != Bundle.ACTIVE
-		                    && bundle.adapt(BundleStartLevel.class).isPersistentlyStarted())) {
-		    	// do no start bundles when user request it
-		    	Long bundleId = bundle.getBundleId();
-		    	BundleInfo bundleInfo = state.bundleInfos.get(bundleId);
-		        if (bundleInfo == null || bundleInfo.isStart()) {
-		            try {
-		                bundle.start();
-		            } catch (BundleException be) {
-		                String msg = format("Could not start bundle %s in feature(s) %s: %s", bundle.getLocation(), getFeaturesContainingBundleList(bundle), be.getMessage());
-		                throw new Exception(msg, be);
-		            }
-		    	}
-		    }
-		}
-	}
-	
-	private boolean isFragment(Bundle b) {
-	    @SuppressWarnings("rawtypes")
+    private void startBundle(InstallationState state, Bundle bundle) throws Exception {
+        if (!isFragment(bundle)) {
+            // do not start bundles that are persistently stopped
+            if (state.installed.contains(bundle)
+                    || (bundle.getState() != Bundle.STARTING && bundle.getState() != Bundle.ACTIVE
+                    && bundle.adapt(BundleStartLevel.class).isPersistentlyStarted())) {
+                // do no start bundles when user request it
+                Long bundleId = bundle.getBundleId();
+                BundleInfo bundleInfo = state.bundleInfos.get(bundleId);
+                if (bundleInfo == null || bundleInfo.isStart()) {
+                    try {
+                        bundle.start();
+                    } catch (BundleException be) {
+                        String msg = format("Could not start bundle %s in feature(s) %s: %s", bundle.getLocation(), getFeaturesContainingBundleList(bundle), be.getMessage());
+                        throw new Exception(msg, be);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean isFragment(Bundle b) {
+        @SuppressWarnings("rawtypes")
         Dictionary d = b.getHeaders();
         String fragmentHostHeader = (String) d.get(Constants.FRAGMENT_HOST);
         return fragmentHostHeader != null && fragmentHostHeader.trim().length() > 0;
-	}
-
-	private void cleanUpOnFailure(InstallationState state, InstallationState failure, boolean noCleanIfFailure) {
-		// cleanup on error
-		if (!noCleanIfFailure) {
-		    HashSet<Bundle> uninstall = new HashSet<Bundle>();
-		    uninstall.addAll(state.installed);
-		    uninstall.addAll(failure.installed);
-		    if (uninstall.size() > 0) {
-		        bundleManager.uninstall(uninstall);
-		    }
-		} else {
-		    // Force start of bundles so that they are flagged as persistently started
-		    for (Bundle b : state.installed) {
-		        try {
-		            b.start();
-		        } catch (Exception e2) {
-		            // Ignore
-		        }
-		    }
-		}
-	}
+    }
+
+    private void cleanUpOnFailure(InstallationState state, InstallationState failure, boolean noCleanIfFailure) {
+        // cleanup on error
+        if (!noCleanIfFailure) {
+            HashSet<Bundle> uninstall = new HashSet<Bundle>();
+            uninstall.addAll(state.installed);
+            uninstall.addAll(failure.installed);
+            if (uninstall.size() > 0) {
+                bundleManager.uninstall(uninstall);
+            }
+        } else {
+            // Force start of bundles so that they are flagged as persistently started
+            for (Bundle b : state.installed) {
+                try {
+                    b.start();
+                } catch (Exception e2) {
+                    // Ignore
+                }
+            }
+        }
+    }
 
     protected void doInstallFeature(InstallationState state, Feature feature, boolean verbose) throws Exception {
         if (feature != null) {
+            if (isInstalled(feature)) {
+                String msg = "Found installed feature " + feature.getName() + " " + feature.getVersion();
+                LOGGER.info(msg);
+                if (verbose) {
+                    System.out.println(msg);
+                }
+                return;
+            }
             String msg = "Installing feature " + feature.getName() + " " + feature.getVersion();
             LOGGER.info(msg);
             if (verbose) {
@@ -576,7 +584,7 @@ public class FeaturesServiceImpl implements FeaturesService {
                 if (result.isNew) {
                     state.installed.add(result.bundle);
                 }
-                String msg2 = (result.isNew) ? "Found installed bundle: " + result.bundle : "Installing bundle " + bInfo.getLocation();
+                String msg2 = (!result.isNew) ? "Found installed bundle: " + result.bundle : "Installing bundle " + bInfo.getLocation();
                 LOGGER.debug(msg2);
                 if (verbose) {
                     System.out.println(msg2);
@@ -590,7 +598,7 @@ public class FeaturesServiceImpl implements FeaturesService {
                 }
 
             }
-            
+
             for (BundleInfo bInfo : feature.getBundles()) {
                 Bundle bundle = bundleManager.isBundleInstalled(bInfo.getLocation());
                 if (bundle != null && !bundles.contains(bundle.getBundleId())) {
@@ -606,11 +614,11 @@ public class FeaturesServiceImpl implements FeaturesService {
         return (bundleStartLevel > 0) ? bundleStartLevel : featureStartLevel;
     }
 
-    private int getBundleStartLevelForOrdering(int startLevel){
+    private int getBundleStartLevelForOrdering(int startLevel) {
         return startLevel == 0 ? KARAF_BUNDLE_START_LEVEL : startLevel;
     }
 
-    protected void doInstallFeatureConditionals(InstallationState state, Feature feature,  boolean verbose) throws Exception {
+    protected void doInstallFeatureConditionals(InstallationState state, Feature feature, boolean verbose) throws Exception {
         //Check conditions of the current feature.
         feature = getFeature(feature.getName(), feature.getVersion());
         if (feature != null) {
@@ -642,19 +650,19 @@ public class FeaturesServiceImpl implements FeaturesService {
             doInstallFeature(state, fi, verbose);
         }
     }
-    
+
     protected List<BundleInfo> resolve(Feature feature) throws Exception {
         String resolver = feature.getResolver();
         // If no resolver is specified, we expect a list of uris
         if (resolver == null || resolver.length() == 0) {
-        	return feature.getBundles();
+            return feature.getBundles();
         }
         boolean optional = false;
         if (resolver.startsWith("(") && resolver.endsWith(")")) {
             resolver = resolver.substring(1, resolver.length() - 1);
             optional = true;
         }
-        
+
 
         @SuppressWarnings("unchecked")
         ServiceTracker<Resolver, Resolver> tracker = bundleManager.createServiceTrackerForResolverName(resolver);
@@ -721,7 +729,7 @@ public class FeaturesServiceImpl implements FeaturesService {
     }
 
     public void uninstallFeature(String name, String version, EnumSet<Option> options) throws Exception {
-    	Feature[] features = getFeatures(name, version);
+        Feature[] features = getFeatures(name, version);
         for (Feature feature : features) {
             if (installed.containsKey(feature)) {
                 boolean verbose = options != null && options.contains(Option.Verbose);
@@ -805,7 +813,7 @@ public class FeaturesServiceImpl implements FeaturesService {
     public Feature[] listFeatures() throws Exception {
         Collection<Feature> features = new ArrayList<Feature>();
         for (Map<String, Feature> featureWithDifferentVersion : getFeatures().values()) {
-			for (Feature f : featureWithDifferentVersion.values()) {
+            for (Feature f : featureWithDifferentVersion.values()) {
                 features.add(f);
             }
         }
@@ -880,11 +888,11 @@ public class FeaturesServiceImpl implements FeaturesService {
 
     protected Map<String, Map<String, Feature>> getFeatures() throws Exception {
         if (features == null) {
-        	//the outer map's key is feature name, the inner map's key is feature version       
+            //the outer map's key is feature name, the inner map's key is feature version
             Map<String, Map<String, Feature>> map = new HashMap<String, Map<String, Feature>>();
             // Two phase load:
             // * first load dependent repositories
-            for (;;) {
+            for (; ; ) {
                 boolean newRepo = false;
                 for (Repository repo : listRepositories()) {
                     for (URI uri : repo.getRepositories()) {
@@ -901,13 +909,13 @@ public class FeaturesServiceImpl implements FeaturesService {
             // * then load all features
             for (Repository repo : repositories.values()) {
                 for (Feature f : repo.getFeatures()) {
-                	if (map.get(f.getName()) == null) {
-                		Map<String, Feature> versionMap = new HashMap<String, Feature>();
-                		versionMap.put(f.getVersion(), f);
-                		map.put(f.getName(), versionMap);
-                	} else {
-                		map.get(f.getName()).put(f.getVersion(), f);
-                	}
+                    if (map.get(f.getName()) == null) {
+                        Map<String, Feature> versionMap = new HashMap<String, Feature>();
+                        versionMap.put(f.getVersion(), f);
+                        map.put(f.getName(), versionMap);
+                    } else {
+                        map.get(f.getName()).put(f.getVersion(), f);
+                    }
                 }
             }
             features = map;
@@ -915,21 +923,21 @@ public class FeaturesServiceImpl implements FeaturesService {
         return features;
     }
 
-	private void initState() {
+    private void initState() {
         if (!loadState()) {
             if (uris != null) {
                 for (URI uri : uris) {
                     try {
-                    	internalAddRepository(uri);
+                        internalAddRepository(uri);
                     } catch (Exception e) {
-                        LOGGER.warn(format("Unable to add features repository %s at startup", uri), e);    
+                        LOGGER.warn(format("Unable to add features repository %s at startup", uri), e);
                     }
                 }
             }
             saveState();
         }
-	}
-    
+    }
+
     public void start() throws Exception {
         this.eventAdminListener = bundleManager.createAndRegisterEventAdminListener();
         initState();
@@ -978,11 +986,11 @@ public class FeaturesServiceImpl implements FeaturesService {
             }
             Set<URI> repositories = loadSet(props, "repositories.");
             for (URI repo : repositories) {
-            	try {
-            		internalAddRepository(repo);
-            	} catch (Exception e) {
-            		LOGGER.warn(format("Unable to add features repository %s at startup", repo), e);
-            	}
+                try {
+                    internalAddRepository(repo);
+                } catch (Exception e) {
+                    LOGGER.warn(format("Unable to add features repository %s at startup", repo), e);
+                }
             }
             installed = loadMap(props, "features.");
             for (Feature f : installed.keySet()) {
@@ -1036,7 +1044,7 @@ public class FeaturesServiceImpl implements FeaturesService {
 
     protected Map<Feature, Set<Long>> loadMap(Properties props, String prefix) {
         Map<Feature, Set<Long>> map = new HashMap<Feature, Set<Long>>();
-        for (@SuppressWarnings("rawtypes") Enumeration e = props.propertyNames(); e.hasMoreElements();) {
+        for (@SuppressWarnings("rawtypes") Enumeration e = props.propertyNames(); e.hasMoreElements(); ) {
             String key = (String) e.nextElement();
             if (key.startsWith(prefix)) {
                 String val = (String) props.get(key);
@@ -1061,9 +1069,9 @@ public class FeaturesServiceImpl implements FeaturesService {
     protected Set<Long> readValue(String val) {
         Set<Long> set = new HashSet<Long>();
         if (val != null && val.length() != 0) {
-        	for (String str : val.split(",")) {
-        		set.add(Long.parseLong(str));
-        	}
+            for (String str : val.split(",")) {
+                set.add(Long.parseLong(str));
+            }
         }
         return set;
     }
@@ -1086,10 +1094,10 @@ public class FeaturesServiceImpl implements FeaturesService {
         }
     }
 
-    static Pattern fuzzyVersion  = Pattern.compile("(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?",
-                                                   Pattern.DOTALL);
+    static Pattern fuzzyVersion = Pattern.compile("(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?",
+            Pattern.DOTALL);
     static Pattern fuzzyModifier = Pattern.compile("(\\d+[.-])*(.*)",
-                                                   Pattern.DOTALL);
+            Pattern.DOTALL);
 
     /**
      * Clean up version parameters. Other builders use more fuzzy definitions of
@@ -1147,7 +1155,7 @@ public class FeaturesServiceImpl implements FeaturesService {
         }
     }
 
-    public Set<Feature> getFeaturesContainingBundle (Bundle bundle) throws Exception {
+    public Set<Feature> getFeaturesContainingBundle(Bundle bundle) throws Exception {
         Set<Feature> features = new HashSet<Feature>();
         for (Map<String, Feature> featureMap : this.getFeatures().values()) {
             for (Feature f : featureMap.values()) {
@@ -1167,7 +1175,7 @@ public class FeaturesServiceImpl implements FeaturesService {
         StringBuilder buffer = new StringBuilder();
         Iterator<Feature> iter = features.iterator();
         while (iter.hasNext()) {
-            Feature feature= iter.next();
+            Feature feature = iter.next();
             buffer.append(feature.getId());
             if (iter.hasNext()) {
                 buffer.append(", ");
@@ -1178,6 +1186,7 @@ public class FeaturesServiceImpl implements FeaturesService {
 
     /**
      * Returns the {@link Feature} that matches the {@link Dependency}.
+     *
      * @param dependency
      * @return
      * @throws Exception
@@ -1215,19 +1224,20 @@ public class FeaturesServiceImpl implements FeaturesService {
     /**
      * Estimates if the {@link List} of {@link Dependency} is satisfied.
      * The method will look into {@link Feature}s that are already installed or now being installed (if {@link InstallationState} is provided (not null)).
+     *
      * @param dependencies
      * @param state
      * @return
      */
     private boolean dependenciesSatisfied(List<? extends Dependency> dependencies, InstallationState state) throws Exception {
-       boolean satisfied = true;
-       for (Dependency dep : dependencies) {
-           Feature f = getFeatureForDependency(dep);
-           if (f != null && !isInstalled(f) && (state != null && !state.features.keySet().contains(f))) {
-               satisfied = false;
-           }
-       }
-       return satisfied;
+        boolean satisfied = true;
+        for (Dependency dep : dependencies) {
+            Feature f = getFeatureForDependency(dep);
+            if (f != null && !isInstalled(f) && (state != null && !state.features.keySet().contains(f))) {
+                satisfied = false;
+            }
+        }
+        return satisfied;
     }
 
     public boolean isRespectStartLvlDuringFeatureUninstall() {

http://git-wip-us.apache.org/repos/asf/karaf/blob/06f35ca4/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java b/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
index b86565f..d23849e 100644
--- a/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
@@ -340,8 +340,7 @@ public class FeaturesServiceTest extends TestBase {
         expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
         expect(bundleManager.getBundleContext()).andReturn(null);
         expect(bundleManager.installBundleIfNeeded(bundleVer01Uri, 0, null)).andReturn(new BundleInstallerResult(bundleVer01, true));
-        expect(bundleManager.installBundleIfNeeded(bundleVer01Uri, 0, null)).andReturn(new BundleInstallerResult(bundleVer01, false));
-        expect(bundleManager.isBundleInstalled("bundle-0.1")).andReturn(bundleVer01).times(2);
+        expect(bundleManager.isBundleInstalled("bundle-0.1")).andReturn(bundleVer01);
         expect(bundleManager.getBundleContext()).andReturn(bundleContext);
         ignoreRefreshes(bundleManager);
         bundleManager.uninstall(Collections.EMPTY_LIST, true);