/** * Copyright 2011-2012 Universite Joseph Fourier, LIG, ADELE team * 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 fr.imag.adele.apam; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.concurrent.ConcurrentSkipListSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.imag.adele.apam.impl.APAMImpl; import fr.imag.adele.apam.impl.CompositeTypeImpl; public class ApamManagers { private static Logger logger = LoggerFactory.getLogger(ApamManagers.class); /* * A thread-safe set of managers, optionally ordered by a given order. * */ private static class ManagerSet<M extends Manager> extends ConcurrentSkipListSet<M> { private static final long serialVersionUID = 2842254142921026458L; public ManagerSet(Comparator<? super M> order) { super(order); } public ManagerSet() { this(NAME_ORDER); } } /** * The default order for manager sets,is based on the lexicographic order of the name */ private final static Comparator<Manager> NAME_ORDER = new Comparator<Manager>() { @Override public int compare(Manager manager1, Manager manager2) { return manager1.getName().compareTo(manager2.getName()); } }; /** * The set of registered managers, classified by the kind of manager */ private static Set<Manager> managers = new ManagerSet<Manager>(); private static Set<ContextualManager> contextualManagers = new ManagerSet<ContextualManager>(); private static Set<DeploymentManager> deploymentManagers = new ManagerSet<DeploymentManager>(); private static Set<DynamicManager> dynamicManagers = new ManagerSet<DynamicManager>(); private static Set<PropertyManager> propertyManagers = new ManagerSet<PropertyManager>(); /** * This class represents an order for managers based on priorities, as defined for relation managers. * * - If no priority is specified for a manager, it is considered low priority. * - If two managers have the same priority, the default name based order is used to break tie */ private static class PriorityOrder implements Comparator<RelationManager> { private final Map<RelationManager,RelationManager.Priority> priorities; public PriorityOrder() { priorities = new HashMap<RelationManager, RelationManager.Priority>(); } public synchronized void setPriority(RelationManager manager, RelationManager.Priority priority) { priorities.put(manager, priority); } private synchronized RelationManager.Priority getPriority(RelationManager manager) { RelationManager.Priority priority = priorities.get(manager); return priority != null ? priority : RelationManager.Priority.LOW; } @Override public int compare(RelationManager manager1, RelationManager manager2) { RelationManager.Priority priority1 = getPriority(manager1); RelationManager.Priority priority2 = getPriority(manager2); return priority1 != priority2 ? priority1.compareTo(priority2) : NAME_ORDER.compare(manager1, manager2); } } /** * The list of relation managers, with their priorities */ private static PriorityOrder priorities = new PriorityOrder(); private static SortedSet<RelationManager> relationManagers = new ManagerSet<RelationManager>(priorities); private static void register(Manager manager) { if (managers.contains(manager)) { return; } managers.add(manager); ((APAMImpl) CST.apam).managerRegistered(manager); logger.info("[" + manager.getName() + "] registered and initialized"); /* * Initialize contextual managers for all context that were created before the * manager registered */ if (manager instanceof ContextualManager) { initializeContextualManager(ContextualManager.class.cast(manager),CompositeTypeImpl.getRootCompositeType()); } if (manager instanceof DeploymentManager) deploymentManagers.add((DeploymentManager)manager); if (manager instanceof ContextualManager) contextualManagers.add((ContextualManager)manager); } private static void initializeContextualManager(ContextualManager manager, CompositeType context) { manager.initializeContext(context); for (CompositeType nested : context.getEmbedded()) { initializeContextualManager(manager,nested); } } private static void unregister(Manager manager) { boolean managerRemoved = managers.remove(manager); if (managerRemoved && manager.getName() != null) { logger.info("[" + manager.getName() + " unregistered]"); } else { logger.error("[" + manager.getName() + " could NOT be unregistered]"); } if (manager instanceof DeploymentManager) deploymentManagers.remove(manager); if (manager instanceof ContextualManager) contextualManagers.remove((ContextualManager)manager); } /** * Adds a new manager to listen for dynamic events * */ public static void addDynamicManager(DynamicManager manager) { register(manager); ApamManagers.dynamicManagers.add(manager); } /** * This manager is interested in knowing when instance properties have been * changed. * * @param manager */ public static void addPropertyManager(PropertyManager manager) { register(manager); ApamManagers.propertyManagers.add(manager); } /** * Adds a manager to Apam. * * @param manager * @param priority * : the relative priority. the lower the interger, the higher * the priority. 0 is reserved for apamman. */ public static void addRelationManager(RelationManager manager, RelationManager.Priority priority) { register(manager); priorities.setPriority(manager, priority); relationManagers.add(manager); } /** * * @return the list of known managers */ public static Set<DynamicManager> getDynamicManagers() { return Collections.unmodifiableSet(dynamicManagers); } /** * * @return the list of known managers */ public static Set<DeploymentManager> getDeploymentManagers() { return Collections.unmodifiableSet(deploymentManagers); } /** * * @return the list of known managers */ public static Set<ContextualManager> getContextualManagers() { return Collections.unmodifiableSet(contextualManagers); } /** * * @return the list of known managers */ public static Set<PropertyManager> getPropertyManagers() { return Collections.unmodifiableSet(propertyManagers); } /** * * @return the list of known managers */ public static SortedSet<RelationManager> getRelationManagers() { return Collections.unmodifiableSortedSet(relationManagers); } /* * Notification events for dynamic events */ public static void notifyAddedInApam(Component newComponent) { for (DynamicManager manager : ApamManagers.dynamicManagers) { manager.addedComponent(newComponent); } } /* * Notification events for property changes */ public static void notifyAttributeAdded(Component component, String attr, String value) { for (PropertyManager manager : ApamManagers.propertyManagers) { manager.attributeAdded(component, attr, value); } } public static void notifyAttributeChanged(Component component, String attr, String newValue, String oldValue) { for (PropertyManager manager : ApamManagers.propertyManagers) { manager.attributeChanged(component, attr, newValue, oldValue); } } public static void notifyAttributeRemoved(Component component, String attr, String oldValue) { for (PropertyManager manager : ApamManagers.propertyManagers) { manager.attributeRemoved(component, attr, oldValue); } } public static void notifyRemovedFromApam(Component lostComponent) { for (DynamicManager manager : ApamManagers.dynamicManagers) { manager.removedComponent(lostComponent); } } public static void removeDynamicManager(DynamicManager manager) { unregister(manager); boolean managerRemoved = ApamManagers.dynamicManagers.remove(manager); if (!managerRemoved) { logger.error("impossible to remove dynamic manager {}", manager.getName()); } } /** * The manager is no longer interested in knowing when instance properties * have been changed * * @param manager */ public static void removePropertyManager(PropertyManager manager) { unregister(manager); boolean managerRemoved = ApamManagers.propertyManagers.remove(manager); if (!managerRemoved) { logger.error("impossible to remove property manager {}", manager.getName()); } } /** * Remove the manager * * @param manager */ public static void removeRelationManager(RelationManager manager) { unregister(manager); boolean removedManager = ApamManagers.relationManagers.remove(manager); if (!removedManager) { logger.error("impossible to remove manager {} from main list", manager.getName()); } } }