blob: 3bbf34b970c76c1257dcca06ab9fa20a638dccf9 [file] [log] [blame]
/*
* 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 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;
import org.apache.karaf.cellar.core.event.EventType;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeatureEvent;
import org.apache.karaf.features.RepositoryEvent;
import org.osgi.service.cm.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Dictionary;
import java.util.Map;
import java.util.Set;
/**
* Local features listener.
*/
public class LocalFeaturesListener extends FeaturesSupport implements org.apache.karaf.features.FeaturesListener {
private static final transient Logger LOGGER = LoggerFactory.getLogger(LocalFeaturesListener.class);
private EventProducer eventProducer;
@Override
public void init() {
super.init();
}
@Override
public void destroy() {
super.destroy();
}
/**
* This method is called when a local feature has changed.
*
* @param event the local feature event.
*/
@Override
public void featureEvent(FeatureEvent event) {
if (!isEnabled()) {
LOGGER.trace("CELLAR FEATURE: local listener is disabled");
return;
}
// check if the producer is ON
if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
LOGGER.debug("CELLAR FEATURE: cluster event producer is OFF");
return;
}
if (event != null) {
Set<Group> groups = groupManager.listLocalGroups();
if (groups != null && !groups.isEmpty()) {
for (Group group : groups) {
Feature feature = event.getFeature();
String name = feature.getName();
String version = feature.getVersion();
if (isAllowed(group, Constants.CATEGORY, name, EventType.OUTBOUND)) {
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())) {
clusterFeatureState.setInstalled(Boolean.TRUE);
} else {
clusterFeatureState.setInstalled(Boolean.FALSE);
}
clusterFeatures.put(event.getFeature().getName() + "/" + event.getFeature().getVersion(), clusterFeatureState);
// broadcast the event
ClusterFeaturesEvent featureEvent = new ClusterFeaturesEvent(name, version, type);
featureEvent.setSourceGroup(group);
featureEvent.setSourceNode(clusterManager.getNode());
eventProducer.produce(featureEvent);
} else LOGGER.trace("CELLAR FEATURE: feature {} is marked BLOCKED OUTBOUND for cluster group {}", name, group.getName());
}
}
}
}
/**
* This method is called when a local features repository has changed.
*
* @param event
*/
@Override
public void repositoryEvent(RepositoryEvent event) {
if (!isEnabled()) {
LOGGER.trace("CELLAR FEATURE: local listener is disabled");
return;
}
// check if the producer is ON
if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
LOGGER.debug("CELLAR FEATURE: cluster event producer is OFF");
return;
}
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
if (event != null && event.getRepository() != null) {
Set<Group> groups = groupManager.listLocalGroups();
if (groups != null && !groups.isEmpty()) {
for (Group group : groups) {
ClusterRepositoryEvent clusterRepositoryEvent = new ClusterRepositoryEvent(event.getRepository().getURI().toString(), event.getType());
clusterRepositoryEvent.setSourceGroup(group);
clusterRepositoryEvent.setSourceNode(clusterManager.getNode());
RepositoryEvent.EventType type = event.getType();
Map<String, String> clusterRepositories = clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + group.getName());
// update the features repositories in the cluster group
if (RepositoryEvent.EventType.RepositoryAdded.equals(type)) {
if (!clusterRepositories.containsKey(event.getRepository().getURI().toString())) {
try {
clusterRepositories.put(event.getRepository().getURI().toString(), event.getRepository().getName());
} catch (Exception e) {
// nothing to do
}
}
// update the features in the cluster group
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 distributed map
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 FEATURE: failed to update the cluster group", e);
}
} else {
// update the repositories in the cluster group
clusterRepositories.remove(event.getRepository().getURI().toString());
// update the features in the cluster group
Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + group.getName());
try {
for (Feature feature : event.getRepository().getFeatures()) {
clusterFeatures.remove(feature.getName() + "/" + feature.getVersion());
}
} catch (Exception e) {
LOGGER.warn("CELLAR FEATURE: failed to update the cluster group", e);
}
}
// broadcast the cluster event
eventProducer.produce(clusterRepositoryEvent);
}
}
}
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
/**
* Check if the local node feature listener is enabled in the etc/org.apache.karaf.cellar.groups.cfg.
*
* @return true if enabled, false else.
*/
private boolean isEnabled() {
try {
Configuration configuration = configurationAdmin.getConfiguration(Configurations.NODE, null);
Dictionary<String, Object> properties = configuration.getProperties();
if (properties != null) {
String value = properties.get(Constants.CATEGORY + Configurations.SEPARATOR + Configurations.LISTENER).toString();
return Boolean.parseBoolean(value);
}
} catch (Exception e) {
LOGGER.warn("CELLAR FEATURE: can't check listener configuration", e);
}
return false;
}
public EventProducer getEventProducer() {
return eventProducer;
}
public void setEventProducer(EventProducer eventProducer) {
this.eventProducer = eventProducer;
}
}