浏览代码

AMBARI-7004 - Views: Need ability to remove view event listener.

tbeerbower 10 年之前
父节点
当前提交
8ca145bbda

+ 9 - 0
ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java

@@ -322,6 +322,15 @@ public class ViewContextImpl implements ViewContext, ViewController {
     viewRegistry.registerListener(listener, viewName, viewVersion);
   }
 
+  @Override
+  public void unregisterListener(Listener listener, String viewName) {
+    viewRegistry.unregisterListener(listener, viewName, null);
+  }
+
+  @Override
+  public void unregisterListener(Listener listener, String viewName, String viewVersion) {
+    viewRegistry.unregisterListener(listener, viewName, viewVersion);
+  }
 
   // ----- helper methods ----------------------------------------------------
 

+ 25 - 5
ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java

@@ -37,6 +37,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
@@ -46,6 +47,7 @@ import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Unmarshaller;
 
+import com.google.common.collect.Sets;
 import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl;
 import org.apache.ambari.server.api.resources.SubResourceDefinition;
 import org.apache.ambari.server.api.resources.ViewExternalSubResourceDefinition;
@@ -135,8 +137,8 @@ public class ViewRegistry {
   /**
    * Mapping of view names to registered listeners.
    */
-  private final Map<String, List<Listener>> listeners =
-      new HashMap<String, List<Listener>>();
+  private final Map<String, Set<Listener>> listeners =
+      new ConcurrentHashMap<String, Set<Listener>>();
 
   /**
    * Helper class.
@@ -633,16 +635,34 @@ public class ViewRegistry {
 
     String name = viewVersion == null ? viewName : ViewEntity.getViewName(viewName, viewVersion);
 
-    List<Listener> listeners = this.listeners.get(name);
+    Set<Listener> listeners = this.listeners.get(name);
 
     if (listeners == null) {
-      listeners = new LinkedList<Listener>();
+      listeners = Sets.newSetFromMap(new ConcurrentHashMap<Listener, Boolean>());
       this.listeners.put(name, listeners);
     }
 
     listeners.add(listener);
   }
 
+  /**
+   * Un-register the given listener from the view identified by the given name and version.
+   *
+   * @param listener     the listener
+   * @param viewName     the view name
+   * @param viewVersion  the view version; null indicates all versions
+   */
+  public synchronized void unregisterListener(Listener listener, String viewName, String viewVersion) {
+
+    String name = viewVersion == null ? viewName : ViewEntity.getViewName(viewName, viewVersion);
+
+    Set<Listener> listeners = this.listeners.get(name);
+
+    if (listeners != null) {
+      listeners.remove(listener);
+    }
+  }
+
   /**
    * Determine whether or not the access specified by the given permission
    * is permitted for the given user on the view instance identified by
@@ -1212,7 +1232,7 @@ public class ViewRegistry {
 
   // notify the view identified by the given view name of the given event
   private void fireEvent(Event event, String viewName) {
-    List<Listener> listeners = this.listeners.get(viewName);
+    Set<Listener> listeners = this.listeners.get(viewName);
 
     if (listeners != null) {
       for (Listener listener : listeners) {

+ 50 - 0
ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java

@@ -412,6 +412,56 @@ public class ViewRegistryTest {
 
     listener.clear();
 
+    // fire an event for a different view
+    event = EventImplTest.getEvent("MyEvent", Collections.<String, String>emptyMap(), view_xml2);
+
+    registry.fireEvent(event);
+
+    Assert.assertNull(listener.getLastEvent());
+
+    // un-register the listener
+    registry.unregisterListener(listener, "MY_VIEW", "1.0.0");
+
+    event = EventImplTest.getEvent("MyEvent", Collections.<String, String>emptyMap(), view_xml1);
+
+    registry.fireEvent(event);
+
+    Assert.assertNull(listener.getLastEvent());
+  }
+
+  @Test
+  public void testListener_allVersions() throws Exception {
+    ViewRegistry registry = getRegistry();
+
+    TestListener listener = new TestListener();
+    registry.registerListener(listener, "MY_VIEW", null); // all versions of MY_VIEW
+
+    EventImpl event = EventImplTest.getEvent("MyEvent", Collections.<String, String>emptyMap(), view_xml1);
+
+    registry.fireEvent(event);
+
+    Assert.assertEquals(event, listener.getLastEvent());
+
+    listener.clear();
+
+    // fire an event for a different view
+    event = EventImplTest.getEvent("MyEvent", Collections.<String, String>emptyMap(), view_xml2);
+
+    registry.fireEvent(event);
+
+    Assert.assertEquals(event, listener.getLastEvent());
+
+    listener.clear();
+
+    // un-register the listener
+    registry.unregisterListener(listener, "MY_VIEW", null); // all versions of MY_VIEW
+
+    event = EventImplTest.getEvent("MyEvent", Collections.<String, String>emptyMap(), view_xml1);
+
+    registry.fireEvent(event);
+
+    Assert.assertNull(listener.getLastEvent());
+
     event = EventImplTest.getEvent("MyEvent", Collections.<String, String>emptyMap(), view_xml2);
 
     registry.fireEvent(event);

+ 19 - 0
ambari-views/src/main/java/org/apache/ambari/view/ViewController.java

@@ -53,4 +53,23 @@ public interface ViewController {
    * @param viewVersion  the view version
    */
   public void registerListener(Listener listener, String viewName, String viewVersion);
+
+  /**
+   * Un-register the listener that is registered for the view identified by the
+   * given name.
+   *
+   * @param listener  the listener
+   * @param viewName  the view to listen to
+   */
+  public void unregisterListener(Listener listener, String viewName);
+
+  /**
+   * Un-register the listener that is registered for the view identified by the
+   * given name and version.
+   *
+   * @param listener     the listener
+   * @param viewName     the view to listen to
+   * @param viewVersion  the view version
+   */
+  public void unregisterListener(Listener listener, String viewName, String viewVersion);
 }