Coverage Report - org.mule.impl.internal.notifications.ServerNotificationManager
 
Classes in this File Line Coverage Branch Coverage Complexity
ServerNotificationManager
0%
0/72
0%
0/16
2.632
ServerNotificationManager$Listener
0%
0/24
0%
0/7
2.632
 
 1  
 /*
 2  
  * $Id: ServerNotificationManager.java 7976 2007-08-21 14:26:13Z dirk.olmes $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.impl.internal.notifications;
 12  
 
 13  
 import org.mule.MuleManager;
 14  
 import org.mule.config.i18n.CoreMessages;
 15  
 import org.mule.routing.filters.WildcardFilter;
 16  
 import org.mule.umo.lifecycle.Disposable;
 17  
 import org.mule.umo.lifecycle.LifecycleException;
 18  
 import org.mule.umo.manager.UMOServerNotification;
 19  
 import org.mule.umo.manager.UMOServerNotificationListener;
 20  
 import org.mule.umo.manager.UMOWorkManager;
 21  
 import org.mule.util.concurrent.ConcurrentHashSet;
 22  
 
 23  
 import java.util.ArrayList;
 24  
 import java.util.Iterator;
 25  
 import java.util.List;
 26  
 import java.util.Set;
 27  
 
 28  
 import javax.resource.spi.work.Work;
 29  
 import javax.resource.spi.work.WorkException;
 30  
 import javax.resource.spi.work.WorkListener;
 31  
 import javax.resource.spi.work.WorkManager;
 32  
 
 33  
 import edu.emory.mathcs.backport.java.util.concurrent.BlockingDeque;
 34  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
 35  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentMap;
 36  
 import edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingDeque;
 37  
 import org.apache.commons.logging.Log;
 38  
 import org.apache.commons.logging.LogFactory;
 39  
 
 40  
 /**
 41  
  * <code>ServerNotificationManager</code> manages all server listeners for a Mule
 42  
  * instance.
 43  
  */
 44  0
 public class ServerNotificationManager implements Work, Disposable
 45  
 {
 46  
     /**
 47  
      * logger used by this class
 48  
      */
 49  0
     protected static final Log logger = LogFactory.getLog(ServerNotificationManager.class);
 50  
 
 51  
     public static final String NULL_SUBSCRIPTION = "NULL";
 52  
 
 53  
     private ConcurrentMap eventsMap;
 54  
     private BlockingDeque eventQueue;
 55  
     private Set listeners;
 56  
     private WorkListener workListener;
 57  0
     private volatile boolean disposed = false;
 58  
 
 59  
     public ServerNotificationManager()
 60  0
     {
 61  0
         eventsMap = new ConcurrentHashMap();
 62  0
         eventQueue = new LinkedBlockingDeque();
 63  0
         listeners = new ConcurrentHashSet();
 64  0
         workListener = MuleManager.getConfiguration().getWorkListener();
 65  0
     }
 66  
 
 67  
     public void start(UMOWorkManager workManager) throws LifecycleException
 68  
     {
 69  
         try
 70  
         {
 71  0
             workManager.scheduleWork(this, WorkManager.INDEFINITE, null, workListener);
 72  
         }
 73  0
         catch (WorkException e)
 74  
         {
 75  0
             throw new LifecycleException(e, this);
 76  0
         }
 77  0
     }
 78  
 
 79  
     public void registerEventType(Class eventType, Class listenerType)
 80  
     {
 81  0
         if (UMOServerNotification.class.isAssignableFrom(eventType))
 82  
         {
 83  0
             Class previousEventType = (Class) eventsMap.putIfAbsent(listenerType, eventType);
 84  0
             if (previousEventType != null)
 85  
             {
 86  0
                 eventType = previousEventType;
 87  
             }
 88  
             else
 89  
             {
 90  0
                 if (logger.isDebugEnabled())
 91  
                 {
 92  0
                     logger.debug("Registered event type: " + eventType);
 93  0
                     logger.debug("Binding listener type '" + listenerType + "' to event type '" + eventType + "'");
 94  
                 }
 95  
             }
 96  
         }
 97  
         else
 98  
         {
 99  0
             throw new IllegalArgumentException(
 100  
                 CoreMessages.propertyIsNotSupportedType("eventType",
 101  
                 UMOServerNotification.class, eventType).getMessage());
 102  
         }
 103  0
     }
 104  
 
 105  
     public void registerListener(UMOServerNotificationListener listener) throws NotificationException
 106  
     {
 107  0
         this.registerListener(listener, null);
 108  0
     }
 109  
 
 110  
     public void registerListener(UMOServerNotificationListener listener, String subscription)
 111  
         throws NotificationException
 112  
     {
 113  0
         listeners.add(new Listener(listener, subscription));
 114  0
     }
 115  
 
 116  
     public void unregisterListener(UMOServerNotificationListener listener)
 117  
     {
 118  0
         for (Iterator iterator = listeners.iterator(); iterator.hasNext();)
 119  
         {
 120  0
             Listener l = (Listener) iterator.next();
 121  0
             if (l.getListenerObject().equals(listener))
 122  
             {
 123  0
                 listeners.remove(l);
 124  0
                 break;
 125  
             }
 126  
         }
 127  0
     }
 128  
 
 129  
     public void fireEvent(UMOServerNotification notification)
 130  
     {
 131  0
         if (disposed)
 132  
         {
 133  0
             return;
 134  
         }
 135  
 
 136  0
         if (notification instanceof BlockingServerEvent)
 137  
         {
 138  0
             this.notifyListeners(notification);
 139  
         }
 140  
         else
 141  
         {
 142  
             try
 143  
             {
 144  0
                 eventQueue.put(notification);
 145  
             }
 146  0
             catch (InterruptedException e)
 147  
             {
 148  0
                 if (!disposed)
 149  
                 {
 150  
                     // TODO MULE-863: Is this sufficient?  Necessary?
 151  0
                     logger.error("Failed to queue notification: " + notification, e);
 152  
                 }
 153  0
             }
 154  
         }
 155  0
     }
 156  
 
 157  
     public void dispose()
 158  
     {
 159  0
         disposed = true;
 160  0
         eventsMap.clear();
 161  0
         eventQueue.clear();
 162  0
         listeners.clear();
 163  0
         workListener = null;
 164  0
     }
 165  
 
 166  
     /**
 167  
      * Exceptions should not be thrown from this method
 168  
      * 
 169  
      * @param notification
 170  
      */
 171  
     protected void notifyListeners(UMOServerNotification notification)
 172  
     {
 173  0
         if (disposed)
 174  
         {
 175  0
             return;
 176  
         }
 177  
 
 178  0
         for (Iterator iterator = listeners.iterator(); iterator.hasNext();)
 179  
         {
 180  0
             Listener listener = (Listener) iterator.next();
 181  0
             if (listener.matches(notification))
 182  
             {
 183  0
                 listener.getListenerObject().onNotification(notification);
 184  
             }
 185  
         }
 186  0
     }
 187  
 
 188  
     public void release()
 189  
     {
 190  0
         this.dispose();
 191  0
     }
 192  
 
 193  
     /**
 194  
      * When an object implementing interface <code>Runnable</code> is used to
 195  
      * create a thread, starting the thread causes the object's <code>run</code>
 196  
      * method to be called in that separately executing thread. <p/> The general
 197  
      * contract of the method <code>run</code> is that it may take any action
 198  
      * whatsoever.
 199  
      * 
 200  
      * @see Thread#run()
 201  
      */
 202  
     public void run()
 203  
     {
 204  0
         while (!disposed)
 205  
         {
 206  
             try
 207  
             {
 208  0
                 UMOServerNotification notification = (UMOServerNotification) eventQueue.take();
 209  0
                 if (notification != null)
 210  
                 {
 211  0
                     this.notifyListeners(notification);
 212  
                 }
 213  
             }
 214  0
             catch (InterruptedException e)
 215  
             {
 216  0
                 if (!disposed)
 217  
                 {
 218  
                     // TODO MULE-863: Is this sufficient?  Necessary? 
 219  0
                     logger.error("Failed to take notification from queue", e);
 220  
                 }
 221  0
             }
 222  
         }
 223  0
     }
 224  
 
 225  
     protected class Listener
 226  
     {
 227  
         private final UMOServerNotificationListener listener;
 228  
         private final List notificationClasses;
 229  
         private final String subscription;
 230  
         private final WildcardFilter subscriptionFilter;
 231  
 
 232  
         public Listener(UMOServerNotificationListener listener, String subscription)
 233  0
         {
 234  0
             this.listener = listener;
 235  0
             this.subscription = (subscription == null ? NULL_SUBSCRIPTION : subscription);
 236  
 
 237  0
             subscriptionFilter = new WildcardFilter(this.subscription);
 238  0
             subscriptionFilter.setCaseSensitive(false);
 239  
 
 240  0
             notificationClasses = new ArrayList();
 241  
 
 242  0
             for (Iterator iterator = eventsMap.keySet().iterator(); iterator.hasNext();)
 243  
             {
 244  0
                 Class clazz = (Class) iterator.next();
 245  0
                 if (clazz.isAssignableFrom(listener.getClass()))
 246  
                 {
 247  0
                     notificationClasses.add(eventsMap.get(clazz));
 248  
                 }
 249  
             }
 250  0
         }
 251  
 
 252  
         public UMOServerNotificationListener getListenerObject()
 253  
         {
 254  0
             return listener;
 255  
         }
 256  
 
 257  
         public List getNotificationClasses()
 258  
         {
 259  0
             return notificationClasses;
 260  
         }
 261  
 
 262  
         public String getSubscription()
 263  
         {
 264  0
             return subscription;
 265  
         }
 266  
 
 267  
         public boolean matches(UMOServerNotification notification)
 268  
         {
 269  0
             if (this.subscriptionMatches(notification))
 270  
             {
 271  0
                 for (Iterator iterator = notificationClasses.iterator(); iterator.hasNext();)
 272  
                 {
 273  0
                     Class notificationClass = (Class) iterator.next();
 274  0
                     if (notificationClass.isAssignableFrom(notification.getClass()))
 275  
                     {
 276  0
                         return true;
 277  
                     }
 278  
                 }
 279  
             }
 280  
 
 281  0
             return false;
 282  
         }
 283  
 
 284  
         public boolean subscriptionMatches(UMOServerNotification notification)
 285  
         {
 286  0
             String resourceId = notification.getResourceIdentifier();
 287  0
             if (NULL_SUBSCRIPTION.equals(subscription) || subscriptionFilter.accept(resourceId))
 288  
             {
 289  0
                 return true;
 290  
             }
 291  
             else
 292  
             {
 293  0
                 return false;
 294  
             }
 295  
         }
 296  
     }
 297  
 
 298  
     public WorkListener getWorkListener()
 299  
     {
 300  0
         return workListener;
 301  
     }
 302  
 
 303  
     public void setWorkListener(WorkListener workListener)
 304  
     {
 305  0
         if (workListener == null)
 306  
         {
 307  0
             throw new IllegalArgumentException("workListener may not be null");
 308  
         }
 309  0
         this.workListener = workListener;
 310  0
     }
 311  
 }