Repository: karaf-cellar Updated Branches: refs/heads/cellar-2.3.x 0ddfe3346 -> 2c4b692a7
[KARAF-3614] Refactore the features distributed map to provide a more reliable sync behavior Project: http://git-wip-us.apache.org/repos/asf/karaf-cellar/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf-cellar/commit/2c4b692a Tree: http://git-wip-us.apache.org/repos/asf/karaf-cellar/tree/2c4b692a Diff: http://git-wip-us.apache.org/repos/asf/karaf-cellar/diff/2c4b692a Branch: refs/heads/cellar-2.3.x Commit: 2c4b692a7d6d62778c7e44b8e6b0f6fd6b1fb5e2 Parents: 0ddfe33 Author: Jean-Baptiste Onofré <[email protected]> Authored: Sat Mar 14 18:14:05 2015 +0100 Committer: Jean-Baptiste Onofré <[email protected]> Committed: Sat Mar 14 18:14:05 2015 +0100 ---------------------------------------------------------------------- assembly/src/main/resources/groups.cfg | 4 +- .../karaf/cellar/bundle/BundleSynchronizer.java | 2 +- .../apache/karaf/cellar/features/Constants.java | 4 +- .../karaf/cellar/features/FeatureInfo.java | 67 ------------ .../karaf/cellar/features/FeatureState.java | 54 ++++++++++ .../cellar/features/FeaturesEventHandler.java | 8 +- .../karaf/cellar/features/FeaturesSupport.java | 82 --------------- .../cellar/features/FeaturesSynchronizer.java | 64 ++++++------ .../cellar/features/LocalFeaturesListener.java | 45 ++++---- .../features/shell/FeatureCommandSupport.java | 90 +--------------- .../features/shell/InstallFeatureCommand.java | 27 ++++- .../features/shell/ListGroupFeatures.java | 15 ++- .../features/shell/UninstallFeatureCommand.java | 26 ++++- .../cellar/features/shell/UrlAddCommand.java | 13 ++- .../cellar/features/shell/UrlListCommand.java | 2 +- .../cellar/features/shell/UrlRemoveCommand.java | 9 +- .../internal/CellarFeaturesMBeanImpl.java | 102 ++++++++----------- 17 files changed, 236 insertions(+), 378 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/assembly/src/main/resources/groups.cfg ---------------------------------------------------------------------- diff --git a/assembly/src/main/resources/groups.cfg b/assembly/src/main/resources/groups.cfg index 3c3b619..0f397c0 100644 --- a/assembly/src/main/resources/groups.cfg +++ b/assembly/src/main/resources/groups.cfg @@ -36,8 +36,8 @@ default.config.blacklist.outbound = org.apache.felix.fileinstall*, \ # default.features.whitelist.inbound = * default.features.whitelist.outbound = * -default.features.blacklist.inbound = config,management,hazelcast,cellar* -default.features.blacklist.outbound = config,management,hazelcast,cellar* +default.features.blacklist.inbound = none +default.features.blacklist.outbound = none # # The following properties define the behavior to use when the node joins the cluster (the usage of the bootstrap http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java ---------------------------------------------------------------------- diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java index ca0f182..fa6b2f1 100644 --- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java +++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java @@ -75,7 +75,7 @@ public class BundleSynchronizer extends BundleSupport implements Synchronizer { } } if (policy != null && policy.equalsIgnoreCase("node")) { - LOGGER.debug("CELLAR BUNDLE: sync policy is set as 'cluster' for cluster group " + group.getName()); + LOGGER.debug("CELLAR BUNDLE: sync policy is set as 'node' for cluster group " + group.getName()); push(group); } } http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/Constants.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/Constants.java b/features/src/main/java/org/apache/karaf/cellar/features/Constants.java index c5a6b55..240db55 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/Constants.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/Constants.java @@ -18,8 +18,8 @@ package org.apache.karaf.cellar.features; */ public class Constants { - // hazelcast map name - public static final String REPOSITORIES_MAP = "org.apache.karaf.cellar.repositories"; + // hazelcast distributed resources name + public static final String REPOSITORIES_LIST = "org.apache.karaf.cellar.repositories"; public static final String FEATURES_MAP = "org.apache.karaf.cellar.features"; // configuration category http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/FeatureInfo.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/FeatureInfo.java b/features/src/main/java/org/apache/karaf/cellar/features/FeatureInfo.java deleted file mode 100644 index 43508bd..0000000 --- a/features/src/main/java/org/apache/karaf/cellar/features/FeatureInfo.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.karaf.cellar.features; - -import java.io.Serializable; - -/** - * Feature info to be store in a cluster group. - */ -public class FeatureInfo implements Serializable { - - private String name; - private String version; - - public FeatureInfo(String name, String version) { - this.name = name; - this.version = version; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - FeatureInfo info = (FeatureInfo) o; - - if (name != null ? !name.equals(info.name) : info.name != null) return false; - if (version != null ? !version.equals(info.version) : info.version != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = name != null ? name.hashCode() : 0; - result = 31 * result + (version != null ? version.hashCode() : 0); - return result; - } - -} http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/FeatureState.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/FeatureState.java b/features/src/main/java/org/apache/karaf/cellar/features/FeatureState.java new file mode 100644 index 0000000..1c2baa2 --- /dev/null +++ b/features/src/main/java/org/apache/karaf/cellar/features/FeatureState.java @@ -0,0 +1,54 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.karaf.cellar.features; + +import java.io.Serializable; + +/** + * Feature info to be store in a cluster group. + */ +public class FeatureState implements Serializable { + + private String name; + private String version; + private Boolean installed; + + public FeatureState() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public Boolean getInstalled() { + return installed; + } + + public void setInstalled(Boolean installed) { + this.installed = installed; + } + +} http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesEventHandler.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesEventHandler.java b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesEventHandler.java index 179d245..dd48a3d 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesEventHandler.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesEventHandler.java @@ -58,13 +58,13 @@ public class FeaturesEventHandler extends FeaturesSupport implements EventHandle // check if the handler switch is ON if (this.getSwitch().getStatus().equals(SwitchStatus.OFF)) { - LOGGER.debug("CELLAR FEATURES_MAP: {} switch is OFF, cluster event is not handled", SWITCH_ID); + LOGGER.debug("CELLAR FEATURES: {} switch is OFF, cluster event is not handled", SWITCH_ID); return; } // check if the group is local if (!groupManager.isLocalGroup(event.getSourceGroup().getName())) { - LOGGER.debug("CELLAR FEATURES_MAP: node is not part of the event cluster group {}", event.getSourceGroup().getName()); + LOGGER.debug("CELLAR FEATURES: node is not part of the event cluster group {}", event.getSourceGroup().getName()); return; } @@ -93,10 +93,10 @@ public class FeaturesEventHandler extends FeaturesSupport implements EventHandle } } else if (FeatureEvent.EventType.FeatureUninstalled.equals(type) && isInstalled) { if (version != null) { - LOGGER.debug("CELLAR FEATURES_MAP: un-installing feature {}/{}", name, version); + LOGGER.debug("CELLAR FEATURES_MAP: uninstalling feature {}/{}", name, version); featuresService.uninstallFeature(name, version); } else { - LOGGER.debug("CELLAR FEATURES_MAP: un-installing feature {}", name); + LOGGER.debug("CELLAR FEATURES_MAP: uninstalling feature {}", name); featuresService.uninstallFeature(name); } } http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSupport.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSupport.java b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSupport.java index 43a9307..6a81aee 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSupport.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSupport.java @@ -81,88 +81,6 @@ public class FeaturesSupport extends CellarSupport { return false; } - /** - * Push a feature in a cluster group - * - * @param feature the feature to push to the cluster group. - * @param group the cluster group where to push the feature. - */ - public void pushFeature(Feature feature, Group group) { - if (feature != null) { - String groupName = group.getName(); - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); - - if (isAllowed(group, Constants.CATEGORY, feature.getName(), EventType.OUTBOUND)) { - if (featuresService != null && clusterFeatures != null) { - FeatureInfo info = new FeatureInfo(feature.getName(), feature.getVersion()); - Boolean installed = featuresService.isInstalled(feature); - clusterFeatures.put(info, installed); - } - } else LOGGER.debug("CELLAR FEATURES_MAP: feature {} is marked BLOCKED OUTBOUND for cluster group {}", feature.getName(), groupName); - } else LOGGER.warn("CELLAR FEATURES_MAP: feature is null"); - } - - /** - * Push a feature in a cluster group. - * This version of the method force the bundle status, without looking the features service. - * - * @param feature the feature to push to the cluster group. - * @param group the cluster group where to push the feature. - * @param force true to force the bundle status as well, false else. - */ - public void pushFeature(Feature feature, Group group, Boolean force) { - if (feature != null) { - String groupName = group.getName(); - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); - - if (isAllowed(group, Constants.CATEGORY, feature.getName(), EventType.OUTBOUND)) { - if (featuresService != null && clusterFeatures != null) { - FeatureInfo info = new FeatureInfo(feature.getName(), feature.getVersion()); - clusterFeatures.put(info, force); - } - } else LOGGER.debug("CELLAR FEATURES_MAP: feature {} is marked BLOCKED OUTBOUND for cluster group {}", feature.getName(), groupName); - } else LOGGER.warn("CELLAR FEATURES_MAP: feature is null"); - } - - /** - * Push a features repository in a cluster group. - * - * @param repository the features repository to push. - * @param group the cluster group where to push. - */ - public void pushRepository(Repository repository, Group group) { - String groupName = group.getName(); - List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName); - - boolean found = false; - for (String clusterRepository : clusterRepositories) { - if (clusterRepository.equals(repository.getURI().toString())) { - found = true; - break; - } - } - - if (!found) { - clusterRepositories.add(repository.getURI().toString()); - } - } - - /** - * Remove a features repository from a cluster group. - * - * @param repository the features repository to remove from the cluster group. - * @param group the cluster group where to remove from. - */ - public void removeRepository(Repository repository, Group group) { - String groupName = group.getName(); - List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName); - - if (featuresService != null && clusterRepositories != null) { - URI uri = repository.getURI(); - clusterRepositories.remove(uri.toString()); - } - } - public FeaturesService getFeaturesService() { return featuresService; } http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java index 72ca64e..128dec2 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java @@ -72,7 +72,7 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize } } if (policy != null && policy.equalsIgnoreCase("node")) { - LOGGER.debug("CELLAR FEATURE: sync policy is set as 'cluster' for cluster group " + group.getName()); + LOGGER.debug("CELLAR FEATURE: sync policy is set as 'node' for cluster group " + group.getName()); push(group); } } @@ -87,37 +87,37 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize if (group != null) { String groupName = group.getName(); LOGGER.debug("CELLAR FEATURES_MAP: pulling features repositories and features from cluster group {}", groupName); - List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName); - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); - clusterManager.getList(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_LIST + Configurations.SEPARATOR + groupName); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + // get features URLs from the cluster group if (clusterRepositories != null && !clusterRepositories.isEmpty()) { for (String url : clusterRepositories) { try { if (!isRepositoryRegisteredLocally(url)) { - LOGGER.debug("CELLAR FEATURES_MAP: adding repository {}", url); + LOGGER.debug("CELLAR FEATURES: adding repository {}", url); featuresService.addRepository(new URI(url)); } } catch (MalformedURLException e) { - LOGGER.warn("CELLAR FEATURES_MAP: failed to add clusterFeatures repository {} (URL is malformed)", url, e); + LOGGER.warn("CELLAR FEATURES: failed to add clusterFeatures repository {} (URL is malformed)", url, e); } catch (Exception e) { - LOGGER.warn("CELLAR FEATURES_MAP: failed to add clusterFeatures repository {}", url, e); + LOGGER.warn("CELLAR FEATURES: failed to add clusterFeatures repository {}", url, e); } } } // get features status from the cluster group if (clusterFeatures != null && !clusterFeatures.isEmpty()) { - for (FeatureInfo info : clusterFeatures.keySet()) { - String name = info.getName(); + for (FeatureState state : clusterFeatures.values()) { + String name = state.getName(); // check if feature is blocked if (isAllowed(group, Constants.CATEGORY, name, EventType.INBOUND)) { - Boolean clusterInstalled = clusterFeatures.get(info); - Boolean locallyInstalled = isFeatureInstalledLocally(info.getName(), info.getVersion()); + Boolean clusterInstalled = state.getInstalled(); + Boolean locallyInstalled = isFeatureInstalledLocally(state.getName(), state.getVersion()); // prevent NPE if (clusterInstalled == null) { @@ -129,22 +129,14 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize // if feature has to be installed locally if (clusterInstalled && !locallyInstalled) { try { - LOGGER.debug("CELLAR FEATURES_MAP: installing feature {}/{}", info.getName(), info.getVersion()); - featuresService.installFeature(info.getName(), info.getVersion()); - } catch (Exception e) { - LOGGER.warn("CELLAR FEATURES_MAP: failed to install feature {}/{} ", new Object[]{info.getName(), info.getVersion()}, e); - } - // if feature has to be uninstalled locally - } else if (!clusterInstalled && locallyInstalled) { - try { - LOGGER.debug("CELLAR FEATURES_MAP: un-installing feature {}/{}", info.getName(), info.getVersion()); - featuresService.uninstallFeature(info.getName(), info.getVersion()); + LOGGER.debug("CELLAR FEATURES: installing feature {}/{}", state.getName(), state.getVersion()); + featuresService.installFeature(state.getName(), state.getVersion()); } catch (Exception e) { - LOGGER.warn("CELLAR FEATURES_MAP: failed to uninstall feature {}/{} ", new Object[]{info.getName(), info.getVersion()}, e); + LOGGER.warn("CELLAR FEATURES: failed to install feature {}/{} ", new Object[]{state.getName(), state.getVersion()}, e); } } } else - LOGGER.warn("CELLAR FEATURES_MAP: feature {} is marked BLOCKED INBOUND for cluster group {}", name, groupName); + LOGGER.warn("CELLAR FEATURES: feature {} is marked BLOCKED INBOUND for cluster group {}", name, groupName); } } } finally { @@ -163,12 +155,14 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize if (group != null) { String groupName = group.getName(); LOGGER.debug("CELLAR FEATURES_MAP: pushing features repositories and features in cluster group {}.", groupName); - clusterManager.getList(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_LIST + Configurations.SEPARATOR + groupName); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + Repository[] repositoryList = new Repository[0]; Feature[] featuresList = new Feature[0]; @@ -176,22 +170,34 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize repositoryList = featuresService.listRepositories(); featuresList = featuresService.listFeatures(); } catch (Exception e) { - LOGGER.warn("CELLAR FEATURES_MAP: unable to list features", e); + LOGGER.warn("CELLAR FEATURES: unable to list features", e); } // push the local features repositories to the cluster group if (repositoryList != null && repositoryList.length > 0) { for (Repository repository : repositoryList) { - pushRepository(repository, group); - LOGGER.debug("CELLAR FEATURES_MAP: pushing repository {} in cluster group {}", repository.getName(), group.getName()); + if (!clusterRepositories.contains(repository.getURI().toString())) { + clusterRepositories.add(repository.getURI().toString()); + LOGGER.debug("CELLAR FEATURES: pushing repository {} in cluster group {}", repository.getName(), groupName); + } else { + LOGGER.debug("CELLAR FEATURES: repository {} is already in cluster group {}", repository.getName(), groupName); + } } } // push the local features status to the cluster group if (featuresList != null && featuresList.length > 0) { for (Feature feature : featuresList) { - pushFeature(feature, group); - LOGGER.debug("CELLAR FEATURES_MAP: pushing feature {} in cluster group {}", feature.getName(), group.getName()); + if (isAllowed(group, Constants.CATEGORY, feature.getName(), EventType.OUTBOUND)) { + FeatureState clusterFeatureState = new FeatureState(); + clusterFeatureState.setName(feature.getName()); + clusterFeatureState.setVersion(feature.getVersion()); + clusterFeatureState.setInstalled(featuresService.isInstalled(feature)); + clusterFeatures.put(feature.getName() + "/" + feature.getVersion(), clusterFeatureState); + LOGGER.debug("CELLAR FEATURES: pushing feature {} in cluster group {}", feature.getName(), group.getName()); + } else { + LOGGER.debug("CELLAR FEATURES: feature {} is marked BLOCKED OUTBOUND for cluster group {}", feature.getName(), group.getName()); + } } } } finally { http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/LocalFeaturesListener.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/LocalFeaturesListener.java b/features/src/main/java/org/apache/karaf/cellar/features/LocalFeaturesListener.java index 3419f88..a9dd88a 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/LocalFeaturesListener.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/LocalFeaturesListener.java @@ -26,6 +26,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Dictionary; +import java.util.List; import java.util.Map; import java.util.Set; @@ -81,11 +82,16 @@ public class LocalFeaturesListener extends FeaturesSupport implements org.apache FeatureEvent.EventType type = event.getType(); // update the features in the cluster group + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + group.getName()); + FeatureState clusterFeatureState = new FeatureState(); + clusterFeatureState.setName(event.getFeature().getName()); + clusterFeatureState.setVersion(event.getFeature().getVersion()); if (FeatureEvent.EventType.FeatureInstalled.equals(event.getType())) { - pushFeature(event.getFeature(), group, true); + clusterFeatureState.setInstalled(Boolean.TRUE); } else { - pushFeature(event.getFeature(), group, false); + clusterFeatureState.setInstalled(Boolean.FALSE); } + clusterFeatures.put(event.getFeature().getName() + "/" + event.getFeature().getVersion(), clusterFeatureState); // broadcast the cluster event ClusterFeaturesEvent featureEvent = new ClusterFeaturesEvent(name, version, type); @@ -129,41 +135,38 @@ public class LocalFeaturesListener extends FeaturesSupport implements org.apache repositoryEvent.setSourceGroup(group); RepositoryEvent.EventType type = event.getType(); + List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_LIST + Configurations.SEPARATOR + group.getName()); + if (RepositoryEvent.EventType.RepositoryAdded.equals(type)) { // update the repositories in the cluster group - pushRepository(event.getRepository(), group); + if (!clusterRepositories.contains(event.getRepository().getURI().toString())) { + clusterRepositories.add(event.getRepository().getURI().toString()); + } // update the features in the cluster group - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + group.getName()); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + group.getName()); try { for (Feature feature : event.getRepository().getFeatures()) { // check the feature in the cluster group - FeatureInfo featureInfo = null; - for (FeatureInfo clusterFeature : clusterFeatures.keySet()) { - if (clusterFeature.getName().equals(feature.getName()) && clusterFeature.getVersion().equals(feature.getVersion())) { - featureInfo = clusterFeature; - break; - } - } - if (featureInfo == null) { - featureInfo = new FeatureInfo(feature.getName(), feature.getVersion()); - clusterFeatures.put(featureInfo, false); - } + FeatureState clusterFeatureState = new FeatureState(); + clusterFeatureState.setName(feature.getName()); + clusterFeatureState.setVersion(feature.getVersion()); + clusterFeatureState.setInstalled(Boolean.FALSE); + clusterFeatures.put(feature.getName() + "/" + feature.getVersion(), clusterFeatureState); } } catch (Exception e) { - LOGGER.warn("CELLAR FEATURES_MAP: failed to update the cluster group", e); + LOGGER.warn("CELLAR FEATURES: failed to update the cluster group", e); } } else { // update the repositories in the cluster group - removeRepository(event.getRepository(), group); + clusterRepositories.remove(event.getRepository().getURI().toString()); // update the features in the cluster group - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + group.getName()); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + group.getName()); try { for (Feature feature : event.getRepository().getFeatures()) { - FeatureInfo info = new FeatureInfo(feature.getName(), feature.getVersion()); - clusterFeatures.remove(info); + clusterFeatures.remove(feature.getName() + "/" + feature.getVersion()); } } catch (Exception e) { - LOGGER.warn("CELLAR FEATURES_MAP: failed to update the cluster group", e); + LOGGER.warn("CELLAR FEATURES: failed to update the cluster group", e); } } http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/shell/FeatureCommandSupport.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/shell/FeatureCommandSupport.java b/features/src/main/java/org/apache/karaf/cellar/features/shell/FeatureCommandSupport.java index 4e543fa..6dcf765 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/shell/FeatureCommandSupport.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/shell/FeatureCommandSupport.java @@ -19,7 +19,7 @@ import org.apache.karaf.cellar.core.Group; import org.apache.karaf.cellar.core.event.EventType; import org.apache.karaf.cellar.core.shell.CellarCommandSupport; import org.apache.karaf.cellar.features.Constants; -import org.apache.karaf.cellar.features.FeatureInfo; +import org.apache.karaf.cellar.features.FeatureState; import org.apache.karaf.features.Feature; import org.apache.karaf.features.FeaturesService; import org.osgi.framework.BundleContext; @@ -33,98 +33,10 @@ import java.util.Map; */ public abstract class FeatureCommandSupport extends CellarCommandSupport { - protected static final transient Logger LOGGER = LoggerFactory.getLogger(FeatureCommandSupport.class); - protected FeaturesService featuresService; protected BundleContext bundleContext; /** - * Forces the features status for a specific group. - * Why? Its required if no group member currently in the cluster. - * If a member of the group joins later, it won't find the change, unless we force it. - * - * @param groupName the cluster group name. - * @param feature the feature name. - * @param version the feature version. - * @param status true to installed, false to uninstalled. - */ - public Boolean updateFeatureStatus(String groupName, String feature, String version, Boolean status) { - Boolean result = Boolean.FALSE; - ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); - Group group = groupManager.findGroupByName(groupName); - if (group == null || group.getNodes().isEmpty()) { - - FeatureInfo info = new FeatureInfo(feature, version); - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); - // check the existing configuration - if (version == null || (version.trim().length() < 1)) { - for (FeatureInfo f : clusterFeatures.keySet()) { - if (f.getName().equals(feature)) { - version = f.getVersion(); - info.setVersion(version); - } - } - } - - // check the features service - try { - for (Feature f : featuresService.listFeatures()) { - if (f.getName().equals(feature)) { - version = f.getVersion(); - info.setVersion(version); - } - } - } catch (Exception e) { - LOGGER.error("Error while browsing features", e); - } - - if (info.getVersion() != null && (info.getVersion().trim().length() > 0)) { - clusterFeatures.put(info, status); - result = Boolean.TRUE; - } - } - } finally { - Thread.currentThread().setContextClassLoader(originalClassLoader); - } - return result; - } - - /** - * Check if a feature is present in a cluster group. - * - * @param groupName the cluster group. - * @param feature the feature name. - * @param version the feature version. - * @return true if the feature exists in the cluster group, false else. - */ - public boolean featureExists(String groupName, String feature, String version) { - ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); - - if (clusterFeatures == null) - return false; - - for (FeatureInfo clusterFeature : clusterFeatures.keySet()) { - if (version == null) { - if (clusterFeature.getName().equals(feature)) - return true; - } else { - if (clusterFeature.getName().equals(feature) && clusterFeature.getVersion().equals(version)) - return true; - } - } - - return false; - } finally { - Thread.currentThread().setContextClassLoader(originalClassLoader); - } - } - - /** * Check if a feature event is allowed. * * @param group the cluster group. http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java b/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java index 7d00bab..2e0fa1f 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java @@ -14,6 +14,7 @@ package org.apache.karaf.cellar.features.shell; import org.apache.felix.gogo.commands.Option; +import org.apache.karaf.cellar.core.Configurations; import org.apache.karaf.cellar.core.Group; import org.apache.karaf.cellar.core.control.SwitchStatus; import org.apache.karaf.cellar.core.event.EventProducer; @@ -22,8 +23,11 @@ import org.apache.karaf.cellar.features.ClusterFeaturesEvent; import org.apache.karaf.cellar.features.Constants; import org.apache.felix.gogo.commands.Argument; import org.apache.felix.gogo.commands.Command; +import org.apache.karaf.cellar.features.FeatureState; import org.apache.karaf.features.FeatureEvent; +import java.util.Map; + @Command(scope = "cluster", name = "feature-install", description = "Install a feature in a cluster group") public class InstallFeatureCommand extends FeatureCommandSupport { @@ -59,8 +63,19 @@ public class InstallFeatureCommand extends FeatureCommandSupport { return null; } + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + + // try to resolve the feature version if not provided + if (version == null) { + for (FeatureState state : clusterFeatures.values()) { + if (state.getName().equals(feature)) { + version = state.getVersion(); + } + } + } + // check if the feature exists in the map - if (!featureExists(groupName, feature, version)) { + if (!clusterFeatures.containsKey(feature + "/" + version)) { if (version != null) System.err.println("Feature " + feature + "/" + version + " doesn't exist in the cluster group " + groupName); else System.err.println("Feature " + feature + " doesn't exist in the cluster group " + groupName); @@ -74,7 +89,15 @@ public class InstallFeatureCommand extends FeatureCommandSupport { } // update the features in the cluster group - updateFeatureStatus(groupName, feature, version, true); + FeatureState clusterFeatureState = clusterFeatures.get(feature + "/" + version); + if (clusterFeatureState == null) { + clusterFeatureState = new FeatureState(); + clusterFeatureState.setName(feature); + clusterFeatureState.setVersion(version); + } + clusterFeatureState.setInstalled(Boolean.TRUE); + clusterFeatures.put(feature + "/" + version, clusterFeatureState); + // TODO does it make sense to also update the cluster bundles, I don't think so ... // broadcast the cluster event ClusterFeaturesEvent event = new ClusterFeaturesEvent(feature, version, noClean, noRefresh, FeatureEvent.EventType.FeatureInstalled); http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/shell/ListGroupFeatures.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/shell/ListGroupFeatures.java b/features/src/main/java/org/apache/karaf/cellar/features/shell/ListGroupFeatures.java index a2b2262..1269d91 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/shell/ListGroupFeatures.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/shell/ListGroupFeatures.java @@ -17,7 +17,7 @@ import org.apache.felix.gogo.commands.Option; import org.apache.karaf.cellar.core.Configurations; import org.apache.karaf.cellar.core.Group; import org.apache.karaf.cellar.features.Constants; -import org.apache.karaf.cellar.features.FeatureInfo; +import org.apache.karaf.cellar.features.FeatureState; import org.apache.felix.gogo.commands.Argument; import org.apache.felix.gogo.commands.Command; @@ -47,23 +47,22 @@ public class ListGroupFeatures extends FeatureCommandSupport { try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); if (clusterFeatures != null && !clusterFeatures.isEmpty()) { System.out.println("Features in cluster group " + groupName); System.out.println(String.format(HEADER_FORMAT, "Status", "Version", "Name")); - for (FeatureInfo info : clusterFeatures.keySet()) { - String name = info.getName(); - String version = info.getVersion(); + for (FeatureState state : clusterFeatures.values()) { + String name = state.getName(); + String version = state.getVersion(); String statusString = ""; - boolean status = clusterFeatures.get(info); - if (status) { + if (state.getInstalled()) { statusString = "installed"; } else { statusString = "uninstalled"; } if (version == null) version = ""; - if (!installed || (installed && status)) { + if (!installed || (installed && state.getInstalled())) { System.out.println(String.format(OUTPUT_FORMAT, statusString, version, name)); } } http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/shell/UninstallFeatureCommand.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/shell/UninstallFeatureCommand.java b/features/src/main/java/org/apache/karaf/cellar/features/shell/UninstallFeatureCommand.java index de1b6de..9c50a2f 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/shell/UninstallFeatureCommand.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/shell/UninstallFeatureCommand.java @@ -13,6 +13,7 @@ */ package org.apache.karaf.cellar.features.shell; +import org.apache.karaf.cellar.core.Configurations; import org.apache.karaf.cellar.core.Group; import org.apache.karaf.cellar.core.control.SwitchStatus; import org.apache.karaf.cellar.core.event.EventProducer; @@ -21,8 +22,11 @@ import org.apache.karaf.cellar.features.ClusterFeaturesEvent; import org.apache.karaf.cellar.features.Constants; import org.apache.felix.gogo.commands.Argument; import org.apache.felix.gogo.commands.Command; +import org.apache.karaf.cellar.features.FeatureState; import org.apache.karaf.features.FeatureEvent; +import java.util.Map; + @Command(scope = "cluster", name = "features-uninstall", description = "Uninstall a feature from a cluster group") public class UninstallFeatureCommand extends FeatureCommandSupport { @@ -52,8 +56,19 @@ public class UninstallFeatureCommand extends FeatureCommandSupport { return null; } + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + + // try to resolve the feature version if not provided + if (version == null) { + for (FeatureState state : clusterFeatures.values()) { + if (state.getName().equals(feature)) { + version = state.getVersion(); + } + } + } + // check if the feature exists in the map - if (!featureExists(groupName, feature, version)) { + if (!clusterFeatures.containsKey(feature + "/" + version)) { if (version != null) System.err.println("Feature " + feature + "/" + version + " doesn't exist in the cluster group " + groupName); else System.err.println("Feature " + feature + " doesn't exist in the cluster group " + groupName); @@ -67,7 +82,14 @@ public class UninstallFeatureCommand extends FeatureCommandSupport { } // update the features in the cluster group - updateFeatureStatus(groupName, feature, version, false); + FeatureState clusterFeatureState = clusterFeatures.get(feature + "/" + version); + if (clusterFeatureState == null) { + clusterFeatureState = new FeatureState(); + clusterFeatureState.setName(feature); + clusterFeatureState.setVersion(version); + } + clusterFeatureState.setInstalled(Boolean.FALSE); + clusterFeatures.put(feature + "/" + version, clusterFeatureState); // broadcast the cluster event ClusterFeaturesEvent event = new ClusterFeaturesEvent(feature, version, FeatureEvent.EventType.FeatureUninstalled); http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlAddCommand.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlAddCommand.java b/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlAddCommand.java index 027798a..6449a39 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlAddCommand.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlAddCommand.java @@ -22,7 +22,7 @@ import org.apache.karaf.cellar.core.control.SwitchStatus; import org.apache.karaf.cellar.core.event.EventProducer; import org.apache.karaf.cellar.features.ClusterRepositoryEvent; import org.apache.karaf.cellar.features.Constants; -import org.apache.karaf.cellar.features.FeatureInfo; +import org.apache.karaf.cellar.features.FeatureState; import org.apache.karaf.features.Feature; import org.apache.karaf.features.Repository; import org.apache.karaf.features.RepositoryEvent; @@ -64,9 +64,9 @@ public class UrlAddCommand extends FeatureCommandSupport { try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); // get the repositories in the cluster group - List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName); + List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_LIST + Configurations.SEPARATOR + groupName); // get the features in the cluster group - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); for (String url : urls) { // check if the URL is already registered @@ -112,8 +112,11 @@ public class UrlAddCommand extends FeatureCommandSupport { // update the features in the cluster group for (Feature feature : repository.getFeatures()) { - FeatureInfo info = new FeatureInfo(feature.getName(), feature.getVersion()); - clusterFeatures.put(info, false); + FeatureState state = new FeatureState(); + state.setName(feature.getName()); + state.setVersion(feature.getVersion()); + state.setInstalled(Boolean.FALSE); + clusterFeatures.put(feature.getName() + "/" + feature.getVersion(), state); } // un-register the repository if it's not local registered http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlListCommand.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlListCommand.java b/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlListCommand.java index 7bc2fd8..fd8860e 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlListCommand.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlListCommand.java @@ -37,7 +37,7 @@ public class UrlListCommand extends FeatureCommandSupport { } // get the repositories in the cluster group - List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName); + List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_LIST + Configurations.SEPARATOR + groupName); for (String clusterRepository : clusterRepositories) { System.out.println(clusterRepository); http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlRemoveCommand.java ---------------------------------------------------------------------- diff --git a/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlRemoveCommand.java b/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlRemoveCommand.java index f52df52..6bbd365 100644 --- a/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlRemoveCommand.java +++ b/features/src/main/java/org/apache/karaf/cellar/features/shell/UrlRemoveCommand.java @@ -22,7 +22,7 @@ import org.apache.karaf.cellar.core.control.SwitchStatus; import org.apache.karaf.cellar.core.event.EventProducer; import org.apache.karaf.cellar.features.ClusterRepositoryEvent; import org.apache.karaf.cellar.features.Constants; -import org.apache.karaf.cellar.features.FeatureInfo; +import org.apache.karaf.cellar.features.FeatureState; import org.apache.karaf.features.Feature; import org.apache.karaf.features.Repository; import org.apache.karaf.features.RepositoryEvent; @@ -61,9 +61,9 @@ public class UrlRemoveCommand extends FeatureCommandSupport { } // get the repositories in the cluster group - List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName); + List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_LIST + Configurations.SEPARATOR + groupName); // get the features in the cluster group - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); for (String url : urls) { // looking for the URL in the list @@ -109,8 +109,7 @@ public class UrlRemoveCommand extends FeatureCommandSupport { // update the features in the cluster group for (Feature feature : repository.getFeatures()) { - FeatureInfo info = new FeatureInfo(feature.getName(), feature.getVersion()); - clusterFeatures.remove(info); + clusterFeatures.remove(feature.getName() + "/" + feature.getVersion()); } // un-register the repository if it's not local registered http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/2c4b692a/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarFeaturesMBeanImpl.java ---------------------------------------------------------------------- diff --git a/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarFeaturesMBeanImpl.java b/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarFeaturesMBeanImpl.java index efc250c..f578940 100644 --- a/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarFeaturesMBeanImpl.java +++ b/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarFeaturesMBeanImpl.java @@ -21,7 +21,7 @@ import org.apache.karaf.cellar.core.event.EventType; import org.apache.karaf.cellar.features.ClusterFeaturesEvent; import org.apache.karaf.cellar.features.ClusterRepositoryEvent; import org.apache.karaf.cellar.features.Constants; -import org.apache.karaf.cellar.features.FeatureInfo; +import org.apache.karaf.cellar.features.FeatureState; import org.apache.karaf.cellar.management.CellarFeaturesMBean; import org.apache.karaf.features.*; import org.osgi.framework.BundleEvent; @@ -117,43 +117,35 @@ public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeat Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); // get the features in the cluster group - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); - // check if the feature exist - FeatureInfo feature = null; - for (FeatureInfo info : clusterFeatures.keySet()) { - if (version == null) { - if (info.getName().equals(name)) { - feature = info; - break; - } - } else { - if (info.getName().equals(name) && info.getVersion().equals(version)) { - feature = info; - break; + // try to resolve version if not provided + if (version == null) { + for (FeatureState state : clusterFeatures.values()) { + if (state.getName().equals(name)) { + version = state.getVersion(); } } } - if (feature == null) { - if (version == null) - throw new IllegalArgumentException("Feature " + name + " doesn't exist in cluster group " + groupName); - else - throw new IllegalArgumentException("Feature " + name + "/" + version + " doesn't exist in cluster group " + groupName); + // check if the feature exists + if (!clusterFeatures.containsKey(name + "/" + version)) { + throw new IllegalArgumentException("Feature " + name + "/" + version + " doesn't exist in cluster group " + groupName); } // update the features in the cluster group - clusterFeatures.put(feature, true); + FeatureState featureState = clusterFeatures.get(name + "/" + version); + featureState.setInstalled(Boolean.TRUE); + clusterFeatures.put(name + "/" + version, featureState); try { - // update the bundles in the cluster group // TODO does it make really sense - List<BundleInfo> bundles = featuresService.getFeature(feature.getName(), version).getBundles(); + List<BundleInfo> bundles = featuresService.getFeature(featureState.getName(), featureState.getVersion()).getBundles(); Map<String, BundleState> clusterBundles = clusterManager.getMap(org.apache.karaf.cellar.bundle.Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName); for (BundleInfo bundle : bundles) { - BundleState state = new BundleState(); - state.setLocation(bundle.getLocation()); - state.setStatus(BundleEvent.STARTED); - clusterBundles.put(bundle.toString(), state); + BundleState bundleState = new BundleState(); + bundleState.setLocation(bundle.getLocation()); + bundleState.setStatus(BundleEvent.STARTED); + clusterBundles.put(bundle.toString(), bundleState); } } catch (Exception e) { // ignore @@ -210,33 +202,26 @@ public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeat Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); // get the features in the cluster group - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); - // check if the feature exist - FeatureInfo feature = null; - for (FeatureInfo info : clusterFeatures.keySet()) { - if (version == null) { - if (info.getName().equals(name)) { - feature = info; - break; - } - } else { - if (info.getName().equals(name) && info.getVersion().equals(version)) { - feature = info; - break; + // resolved the version if not provided + if (version == null) { + for (FeatureState featureState : clusterFeatures.values()) { + if (featureState.getName().equals(name)) { + version = featureState.getVersion(); } } } - if (feature == null) { - if (version == null) - throw new IllegalArgumentException("Feature " + name + " doesn't exist in cluster group " + groupName); - else - throw new IllegalArgumentException("Feature " + name + "/" + version + " doesn't exist in cluster group " + groupName); + // check if the feature exist + if (!clusterFeatures.containsKey(name + "/" + version)) { + throw new IllegalArgumentException("Feature " + name + "/" + version + " doesn't exist in cluster group " + groupName); } // update the cluster group - clusterFeatures.put(feature, false); + FeatureState featureState = clusterFeatures.get(name + "/" + version); + featureState.setInstalled(Boolean.FALSE); + clusterFeatures.put(name + "/" + version, featureState); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } @@ -265,13 +250,12 @@ public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeat ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); try { - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + group); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + group); if (clusterFeatures != null && !clusterFeatures.isEmpty()) { - for (FeatureInfo feature : clusterFeatures.keySet()) { - boolean installed = clusterFeatures.get(feature); + for (FeatureState featureState : clusterFeatures.values()) { CompositeData data = new CompositeDataSupport(compositeType, new String[]{"name", "version", "installed"}, - new Object[]{feature.getName(), feature.getVersion(), installed}); + new Object[]{featureState.getName(), featureState.getVersion(), featureState.getInstalled()}); table.put(data); } } @@ -290,7 +274,7 @@ public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeat } // get the distributed URLs list - List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName); + List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_LIST + Configurations.SEPARATOR + groupName); List<String> result = new ArrayList<String>(); for (String url : clusterRepositories) { @@ -322,9 +306,9 @@ public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeat try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); // get the features repositories in the cluster group - List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName); + List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_LIST + Configurations.SEPARATOR + groupName); // get the features in the cluster group - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); // check if the URL is already registered boolean found = false; @@ -368,8 +352,11 @@ public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeat // update the features in the cluster group for (Feature feature : repository.getFeatures()) { - FeatureInfo info = new FeatureInfo(feature.getName(), feature.getVersion()); - clusterFeatures.put(info, false); + FeatureState state = new FeatureState(); + state.setName(feature.getName()); + state.setVersion(feature.getVersion()); + state.setInstalled(Boolean.FALSE); + clusterFeatures.put(feature.getName() + "/" + feature.getVersion(), state); } // un-register the repository if it's not local registered @@ -408,9 +395,9 @@ public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeat } // get the features repositories in the cluster group - List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName); + List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_LIST + Configurations.SEPARATOR + groupName); // get the features in the cluster group - Map<FeatureInfo, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); + Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName); // looking for the URL in the list boolean found = false; @@ -454,8 +441,7 @@ public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeat // update the features in the cluster group for (Feature feature : repository.getFeatures()) { - FeatureInfo info = new FeatureInfo(feature.getName(), feature.getVersion()); - clusterFeatures.remove(info); + clusterFeatures.remove(feature.getName() + "/" + feature.getVersion()); } // un-register the repository if it's not local registered
