Java tutorial
/* * 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 net.cellar.hazelcast; import com.hazelcast.core.Cluster; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.ITopic; import com.hazelcast.core.Member; import net.cellar.core.Configurations; import net.cellar.core.Dispatcher; import net.cellar.core.Group; import net.cellar.core.GroupManager; import net.cellar.core.Node; import net.cellar.core.Synchronizer; import net.cellar.core.event.EventConsumer; import net.cellar.core.event.EventProducer; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.slf4j.Logger; import org.springframework.osgi.context.BundleContextAware; import java.io.IOException; import java.util.Collection; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.Set; /** * @author: iocanel */ public class HazelcastGroupManager implements GroupManager, BundleContextAware { private static final Logger logger = org.slf4j.LoggerFactory.getLogger(HazelcastClusterManager.class); private static final String GROUPS = "net.cellar.groups"; private Map<String, ServiceRegistration> producerRegistrations = new HashMap<String, ServiceRegistration>(); private Map<String, ServiceRegistration> consumerRegistrations = new HashMap<String, ServiceRegistration>(); private BundleContext bundleContext; private HazelcastInstance instance; private Dispatcher dispatcher; private ConfigurationAdmin configurationAdmin; public void init() throws Exception { //Add group to configuration try { Configuration configuration = configurationAdmin.getConfiguration(Configurations.NODE); Dictionary<String, String> properties = configuration.getProperties(); String groups = properties.get(Configurations.GROUPS_KEY); Set<String> groupNames = convertStringToSet(groups); if (groupNames != null && !groupNames.isEmpty()) { for (String groupName : groupNames) { registerGroup(groupName); } } } catch (IOException e) { logger.error("Error reading group configuration"); } } @Override public Node getNode() { Node node = null; Cluster cluster = instance.getCluster(); if (cluster != null) { Member member = cluster.getLocalMember(); node = new HazelcastNode(member.getInetSocketAddress().getHostName(), member.getInetSocketAddress().getPort()); } return node; } @Override public Group createGroup(String groupName) { Group group = listGroups().get(groupName); if (group == null) group = new Group(groupName); if (!listGroups().containsKey(groupName)) { copyGroupConfiguration(Configurations.DEFAULT_GROUP_NAME, groupName); listGroups().put(groupName, group); } return group; } @Override public void deleteGroup(String groupName) { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { if (!groupName.equals(Configurations.DEFAULT_GROUP_NAME)) listGroups().remove(groupName); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } @Override public Set<Group> listLocalGroups() { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); return listGroups(getNode()); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } @Override public Set<Group> listAllGroups() { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); return new HashSet<Group>(listGroups().values()); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } @Override public Group findGroupByName(String groupName) { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); return listGroups().get(groupName); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } @Override public Map<String, Group> listGroups() { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); return instance.getMap(GROUPS); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } @Override public Set<Group> listGroups(Node node) { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); Set<Group> result = new HashSet<Group>(); Map<String, Group> groupMap = instance.getMap(GROUPS); Collection<Group> groupCollection = groupMap.values(); if (groupCollection != null && !groupCollection.isEmpty()) { for (Group group : groupCollection) { if (group.getMembers().contains(node)) result.add(group); } } return result; } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } @Override public Set<String> listGroupNames() { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); return listGroupNames(getNode()); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } @Override public Set<String> listGroupNames(Node node) { Set<String> names = new HashSet<String>(); ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); Map<String, Group> groups = listGroups(); if (groups != null && !groups.isEmpty()) { for (Group group : groups.values()) { if (group.getMembers().contains(node)) { names.add(group.getName()); } } } } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } return names; } @Override public void registerGroup(Group group) { String groupName = group.getName(); createGroup(groupName); ITopic topic = instance.getTopic(Constants.TOPIC + "." + groupName); Properties serviceProperties = new Properties(); serviceProperties.put("type", "group"); serviceProperties.put("name", groupName); if (!producerRegistrations.containsKey(groupName)) { TopicProducer producer = new TopicProducer(); producer.setTopic(topic); producer.setNode(getNode()); ServiceRegistration producerRegistration = bundleContext .registerService(EventProducer.class.getCanonicalName(), producer, serviceProperties); producerRegistrations.put(groupName, producerRegistration); } if (!consumerRegistrations.containsKey(groupName)) { TopicConsumer consumer = new TopicConsumer(); consumer.setDispatcher(dispatcher); consumer.setTopic(topic); consumer.setNode(getNode()); consumer.init(); ServiceRegistration consumerRegistration = bundleContext .registerService(EventConsumer.class.getCanonicalName(), consumer, serviceProperties); consumerRegistrations.put(groupName, consumerRegistration); } group.getMembers().add(getNode()); listGroups().put(groupName, group); //Add group to configuration try { Configuration configuration = configurationAdmin.getConfiguration(Configurations.NODE); Dictionary<String, String> properties = configuration.getProperties(); String groups = properties.get(Configurations.GROUPS_KEY); if (groups == null || groups.isEmpty()) { groups = groupName; } else { Set<String> groupNamesSet = convertStringToSet(groups); groupNamesSet.add(groupName); groups = convertSetToString(groupNamesSet); } if (groups == null || groups.isEmpty()) { groups = groupName; } properties.put(Configurations.GROUPS_KEY, groups); configuration.update(properties); } catch (IOException e) { logger.error("Error reading group configuration {}", group); } //Sync try { ServiceReference[] serviceReferences = bundleContext .getAllServiceReferences("net.cellar.core.Synchronizer", null); if (serviceReferences != null && serviceReferences.length > 0) { for (ServiceReference ref : serviceReferences) { Synchronizer synchronizer = (Synchronizer) bundleContext.getService(ref); if (synchronizer.isSyncEnabled(group)) { synchronizer.pull(group); synchronizer.push(group); } bundleContext.ungetService(ref); } } } catch (InvalidSyntaxException e) { logger.error("Error looking up for Synchronizers", e); } } @Override public void registerGroup(String groupName) { Group group = listGroups().get(groupName); if (group == null) group = new Group(groupName); registerGroup(group); } @Override public void unRegisterGroup(String groupName) { unRegisterGroup(listGroups().get(groupName)); } public void unRegisterGroup(Group group) { String groupName = group.getName(); //1. Remove local node from group. group.getMembers().remove(getNode()); listGroups().put(groupName, group); //2. Unregister group consumers if (consumerRegistrations != null && !consumerRegistrations.isEmpty()) { ServiceRegistration consumerRegistration = consumerRegistrations.get(groupName); if (consumerRegistration != null) { consumerRegistration.unregister(); consumerRegistrations.remove(groupName); } } //3. Unregister group producers if (producerRegistrations != null && !producerRegistrations.isEmpty()) { ServiceRegistration producerRegistration = producerRegistrations.get(groupName); if (producerRegistration != null) { producerRegistration.unregister(); producerRegistrations.remove(groupName); } } //Remove group from configuration try { Configuration configuration = configurationAdmin.getConfiguration(Configurations.NODE); Dictionary<String, String> properties = configuration.getProperties(); String groups = properties.get(Configurations.GROUPS_KEY); if (groups == null || groups.isEmpty()) { groups = ""; } else if (groups.contains(groupName)) { Set<String> groupNamesSet = convertStringToSet(groups); groupNamesSet.remove(groupName); groups = convertSetToString(groupNamesSet); } properties.put(Configurations.GROUPS_KEY, groups); configuration.update(properties); } catch (IOException e) { logger.error("Error reading group configuration {}", group); } } /** * Copies the setup of a {@link Group}. * * @param sourceGroupName * @param targetGroupName */ public void copyGroupConfiguration(String sourceGroupName, String targetGroupName) { try { Configuration conf = configurationAdmin.getConfiguration(Configurations.GROUP); Dictionary dictionary = conf.getProperties(); Dictionary updatedProperties = new Properties(); Enumeration keyEnumeration = dictionary.keys(); while (keyEnumeration.hasMoreElements()) { String key = (String) keyEnumeration.nextElement(); String value = (String) dictionary.get(key); if (key.startsWith(sourceGroupName)) { String newKey = key.replace(sourceGroupName, targetGroupName); updatedProperties.put(newKey, value); } updatedProperties.put(key, value); } conf.update(updatedProperties); } catch (IOException e) { logger.error("Error reading group configuration ", e); } } /** * Utility method which converts a set to a String. * * @param set * @return */ protected String convertSetToString(Set<String> set) { String result = ""; Iterator<String> groupIterator = set.iterator(); while (groupIterator.hasNext()) { String name = groupIterator.next(); result = result + name; if (groupIterator.hasNext()) result = result + ","; } return result; } /** * Utility method which converts String to Set. * * @param string * @return */ protected Set<String> convertStringToSet(String string) { Set<String> result = new HashSet<String>(); String[] groupNames = string.split(","); if (groupNames != null && groupNames.length > 0) { for (String name : groupNames) { result.add(name); } } else result.add(string); return result; } /** * Returns the {@link Dispatcher} * * @return */ public Dispatcher getDispatcher() { return dispatcher; } /** * Sets the {@link Dispatcher} * * @param dispatcher */ public void setDispatcher(Dispatcher dispatcher) { this.dispatcher = dispatcher; } public HazelcastInstance getInstance() { return instance; } public void setInstance(HazelcastInstance instance) { this.instance = instance; } public BundleContext getBundleContext() { return bundleContext; } public void setBundleContext(BundleContext bundleContext) { this.bundleContext = bundleContext; } public ConfigurationAdmin getConfigurationAdmin() { return configurationAdmin; } public void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) { this.configurationAdmin = configurationAdmin; } }