diff --git a/kar/src/main/java/org/apache/karaf/kar/KarService.java b/kar/src/main/java/org/apache/karaf/kar/KarService.java index 219f9ef..831a77b 100644 --- a/kar/src/main/java/org/apache/karaf/kar/KarService.java +++ b/kar/src/main/java/org/apache/karaf/kar/KarService.java @@ -28,9 +28,9 @@ /** * Install KAR from a given URI - * + * * Resources will be copied to the karaf base dir - * Repository contents will be copied to a subdir in the + * Repository contents will be copied to a subdir in the * karaf data directory * * @param karUri Uri of the kar to be installed @@ -46,11 +46,21 @@ * @throws Exception in case of installation failure */ void install(URI karUri, boolean noAutoStartBundles) throws Exception; - + /** - * Install a kar with manually given repository and + * Install KAR from a given URI + * + * @param karUri URI of the kar to install + * @param noAutoStartBundles true to not start automatically the bundles, false else + * @param noAutoRefreshBundles true to not refresh automatically the bundles, false else + * @throws Exception in case of installation failure + */ + void install(URI karUri, boolean noAutoStartBundles, boolean noAutoRefreshBundles) throws Exception; + + /** + * Install a kar with manually given repository and * resource directories. - * + * * @param karUri Uri of the kar to be installed * @param repoDir destination for the repository contents of the kar * @param resourceDir destination for the resource contents of the kar @@ -78,22 +88,32 @@ void uninstall(String name) throws Exception; /** + * Uninstall the given KAR + * + * @param name the name of the KAR + * @param noAutoRefreshBundles true to not refresh automatically the bundles, false else + * + * @throws Exception in case of failure + */ + void uninstall(String name, boolean noAutoRefreshBundles) throws Exception; + + /** * List the KAR stored in the data folder. - * + * * @return the list of KAR stored. * @throws Exception in case of listing failure. */ List list() throws Exception; - + /** * Create a kar from the given feature and repo names. * Each named feature including all transitive deps will be added. * For each named repo all features in the repo and their transitive deps will be added. - * + * * @param repoName the feature repository to use to create the kar. * @param features the list of features to include in the created kar. * @param console the console stream where to print details. */ void create(String repoName, List features, PrintStream console); - + } diff --git a/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java b/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java index 0f5e544..1299079 100644 --- a/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java +++ b/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java @@ -63,7 +63,7 @@ private File storage; private File base; private FeaturesService featuresService; - + private boolean noAutoRefreshBundles; private boolean noAutoStartBundles; private List unsatisfiedKars; @@ -89,20 +89,30 @@ @Override public void install(URI karUri, boolean noAutoStartBundles) throws Exception { + install(karUri, noAutoStartBundles, isNoAutoRefreshBundles()); + } + + @Override + public void install(URI karUri, boolean noAutoStartBundles, boolean noAutoRefreshBundles) throws Exception { String karName = new Kar(karUri).getKarName(); LOGGER.debug("Installing KAR {} from {}", karName, karUri); File karDir = new File(storage, karName); - install(karUri, karDir, base, noAutoStartBundles); - } + install(karUri, karDir, base, noAutoStartBundles, noAutoRefreshBundles); + } @Override public void install(URI karUri, File repoDir, File resourceDir) throws Exception { install(karUri, repoDir, resourceDir, false); } - + @Override public void install(URI karUri, File repoDir, File resourceDir, boolean noAutoStartBundles) throws Exception { - busy.set(true); + install(karUri, repoDir, resourceDir, noAutoStartBundles, isNoAutoRefreshBundles()); + + } + + private void install(URI karUri, File repoDir, File resourceDir, boolean noAutoStartBundles, boolean noAutoRefreshBundles) throws Exception { + busy.set(true); Kar kar = new Kar(karUri); try { kar.extract(repoDir, resourceDir); @@ -110,18 +120,18 @@ for (URI uri : kar.getFeatureRepos()) { addToFeaturesRepositories(uri); } - + if (kar.isShouldInstallFeatures()) { List featureRepos = kar.getFeatureRepos(); Dependency missingDependency = findMissingDependency(featureRepos); if (missingDependency == null) { - installFeatures(featureRepos, noAutoStartBundles); + installFeatures(featureRepos, noAutoStartBundles, noAutoRefreshBundles); } else { LOGGER.warn("Feature dependency {} is not available. Kar deployment postponed to see if it is about to be deployed",missingDependency); unsatisfiedKars.add(kar); if (delayedDeployerThread == null) { - delayedDeployerThread = new DelayedDeployerThread(noAutoStartBundles); + delayedDeployerThread = new DelayedDeployerThread(noAutoStartBundles, noAutoRefreshBundles); delayedDeployerThread.start(); } } @@ -132,13 +142,13 @@ if(findMissingDependency(delayedKar.getFeatureRepos())==null) { LOGGER.info("Dependencies of kar {} are now satisfied. Installing",delayedKar.getKarName()); iterator.remove(); - installFeatures(delayedKar.getFeatureRepos(), noAutoStartBundles); + installFeatures(delayedKar.getFeatureRepos(), noAutoStartBundles, noAutoRefreshBundles); } } } if (unsatisfiedKars.isEmpty()) { if (delayedDeployerThread != null) { - delayedDeployerThread.cancel(); + delayedDeployerThread.cancel(); } delayedDeployerThread = null; } @@ -150,8 +160,7 @@ } finally { busy.set(false); } - - } + } /** * checks if all required features are available @@ -199,7 +208,7 @@ } return uriList; } - + private void writeToFile(List featuresRepositoriesInKar, File repoListFile) { FileOutputStream fos = null; PrintStream ps = null; @@ -231,21 +240,26 @@ @Override public void uninstall(String karName) throws Exception { - File karDir = new File(storage, karName); - - if (!karDir.exists()) { - throw new IllegalArgumentException("The KAR " + karName + " is not installed"); - } - - List featuresRepositories = readFromFile(new File(karDir, FEATURE_CONFIG_FILE)); - uninstallFeatures(featuresRepositories); - for (URI featuresRepository : featuresRepositories) { - featuresService.removeRepository(featuresRepository); - } - - deleteRecursively(karDir); + uninstall(karName, isNoAutoRefreshBundles()); } - + + @Override + public void uninstall(String karName, boolean noAutoRefreshBundles) throws Exception { + File karDir = new File(storage, karName); + + if (!karDir.exists()) { + throw new IllegalArgumentException("The KAR " + karName + " is not installed"); + } + + List featuresRepositories = readFromFile(new File(karDir, FEATURE_CONFIG_FILE)); + uninstallFeatures(featuresRepositories, noAutoRefreshBundles); + for (URI featuresRepository : featuresRepositories) { + featuresService.removeRepository(featuresRepository); + } + + deleteRecursively(karDir); + } + @Override public List list() throws Exception { List kars = new ArrayList<>(); @@ -280,7 +294,7 @@ * * @param featuresRepositories the list of features XML. */ - private void installFeatures(List featuresRepositories, boolean noAutoStartBundles) throws Exception { + private void installFeatures(List featuresRepositories, boolean noAutoStartBundles, boolean noAutoRefreshBundles) throws Exception { for (Repository repository : featuresService.listRepositories()) { for (URI karFeatureRepoUri : featuresRepositories) { if (repository.getURI().equals(karFeatureRepoUri)) { @@ -289,8 +303,8 @@ if (feature.getInstall() == null || Feature.DEFAULT_INSTALL_MODE.equals(feature.getInstall())) { EnumSet options = EnumSet.noneOf(FeaturesService.Option.class); try { - LOGGER.debug("noAutoRefreshBundles is {}", isNoAutoRefreshBundles()); - if (isNoAutoRefreshBundles()) { + LOGGER.debug("noAutoRefreshBundles is {} (default {})", noAutoRefreshBundles, isNoAutoRefreshBundles()); + if (noAutoRefreshBundles || isNoAutoRefreshBundles()) { options.add(FeaturesService.Option.NoAutoRefreshBundles); } LOGGER.debug("noAutoStartBundles is {} (default {})", noAutoStartBundles, this.noAutoStartBundles); @@ -312,7 +326,7 @@ } } } - + @Override public void create(String repoName, List features, PrintStream console) { FileOutputStream fos = null; @@ -328,17 +342,17 @@ fos = new FileOutputStream(karFile); Manifest manifest = createNonAutoStartManifest(repo.getURI()); jos = new JarOutputStream(new BufferedOutputStream(fos, 100000), manifest); - + Map locationMap = new HashMap<>(); copyResourceToJar(jos, repo.getURI(), locationMap); - + Map featureMap = new HashMap<>(); for (Feature feature : repo.getFeatures()) { featureMap.put(feature.getName(), feature); } - + Set featuresToCopy = getFeatures(featureMap, features, 1); - + for (Feature feature : featuresToCopy) { if (console != null) console.println("Adding feature " + feature.getName()); @@ -353,13 +367,13 @@ closeStream(jos); closeStream(fos); } - + } private Set getFeatures(Map featureMap, List features, int depth) { Set featureSet = new HashSet<>(); if (depth > 5) { - // Break after some recursions to avoid endless loops + // Break after some recursions to avoid endless loops return featureSet; } if (features == null) { @@ -453,15 +467,20 @@ * * @param featuresRepositories the list of features XML. */ - private void uninstallFeatures(List featuresRepositories) throws Exception { + private void uninstallFeatures(List featuresRepositories, boolean noAutoRefreshBundles) throws Exception { for (Repository repository : featuresService.listRepositories()) { for (URI karFeatureRepoUri : featuresRepositories) { if (repository.getURI().equals(karFeatureRepoUri)) { try { for (Feature feature : repository.getFeatures()) { if (feature.getInstall() == null || Feature.DEFAULT_INSTALL_MODE.equals(feature.getInstall())) { + EnumSet options = EnumSet.noneOf(FeaturesService.Option.class); try { - featuresService.uninstallFeature(feature.getName(), feature.getVersion()); + LOGGER.debug("noAutoRefreshBundles is {} (default {})", noAutoRefreshBundles, isNoAutoRefreshBundles()); + if (noAutoRefreshBundles || isNoAutoRefreshBundles()) { + options.add(FeaturesService.Option.NoAutoRefreshBundles); + } + featuresService.uninstallFeature(feature.getName(), feature.getVersion(), options); } catch (Exception e) { LOGGER.warn("Unable to uninstall Kar feature {}", feature.getName() + "/" + feature.getVersion(), e); } @@ -494,21 +513,23 @@ private class DelayedDeployerThread extends Thread { private boolean noAutoStartBundles; + private boolean noAutoRefreshBundles; private AtomicBoolean cancel; - - public DelayedDeployerThread(boolean noAutoStartBundles) { + + public DelayedDeployerThread(boolean noAutoStartBundles, boolean noAutoRefreshBundles) { super("Delayed kar deployment"); cancel = new AtomicBoolean(); this.noAutoStartBundles = noAutoStartBundles; + this.noAutoRefreshBundles = noAutoRefreshBundles; } - + public void cancel() { cancel.set(true); } - + @Override public void run() { - + try { while(busy.get() && !cancel.get()) { Thread.sleep(TimeUnit.SECONDS.toMillis(2)); @@ -525,13 +546,12 @@ for (Iterator iterator = unsatisfiedKars.iterator(); iterator.hasNext();) { Kar kar = iterator.next(); iterator.remove(); - try { - installFeatures(kar.getFeatureRepos(), noAutoStartBundles); + try { + installFeatures(kar.getFeatureRepos(), noAutoStartBundles, noAutoRefreshBundles); } catch (Exception e) { LOGGER.error("Delayed deployment of kar "+kar.getKarName()+" failed",e); } } } } - -} +} \ No newline at end of file