JMXServerRegistry.java
001 /*
002  *
003  * Licensed to the Apache Software Foundation (ASF) under one
004  * or more contributor license agreements.  See the NOTICE file
005  * distributed with this work for additional information
006  * regarding copyright ownership.  The ASF licenses this file
007  * to you under the Apache License, Version 2.0 (the
008  * "License"); you may not use this file except in compliance
009  * with the License.  You may obtain a copy of the License at
010  
011  *   http://www.apache.org/licenses/LICENSE-2.0
012  
013  * Unless required by applicable law or agreed to in writing,
014  * software distributed under the License is distributed on an
015  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016  * KIND, either express or implied.  See the License for the
017  * specific language governing permissions and limitations
018  * under the License.
019  *
020  */
021 package org.apache.qpid.management.ui.jmx;
022 
023 import static org.apache.qpid.management.ui.Constants.ALL;
024 
025 import java.util.ArrayList;
026 import java.util.Collections;
027 import java.util.Date;
028 import java.util.HashMap;
029 import java.util.List;
030 import java.util.concurrent.CopyOnWriteArrayList;
031 
032 import javax.management.ListenerNotFoundException;
033 import javax.management.MBeanInfo;
034 import javax.management.MBeanServerConnection;
035 import javax.management.Notification;
036 import javax.management.ObjectName;
037 import javax.management.remote.JMXConnector;
038 
039 import org.apache.qpid.management.common.JMXConnnectionFactory;
040 import org.apache.qpid.management.ui.ApplicationRegistry;
041 import org.apache.qpid.management.ui.ManagedBean;
042 import org.apache.qpid.management.ui.ManagedServer;
043 import org.apache.qpid.management.ui.ServerRegistry;
044 import org.apache.qpid.management.ui.model.ManagedAttributeModel;
045 import org.apache.qpid.management.ui.model.NotificationInfoModel;
046 import org.apache.qpid.management.ui.model.NotificationObject;
047 import org.apache.qpid.management.ui.model.OperationDataModel;
048 
049 
050 public class JMXServerRegistry extends ServerRegistry
051 {
052     private ObjectName _serverObjectName = null;
053     private JMXConnector _jmxc = null;
054     private MBeanServerConnection _mbsc = null;
055     private String _securityMechanism = null;
056     
057     private List<String> _usersList;
058     // When an mbean gets removed from mbean server, then the notification listener
059     // will add that mbean in this list.
060     private List<ManagedBean> _mbeansToBeRemoved = new ArrayList<ManagedBean>();
061     
062     // Map containing all managed beans and mapped with unique mbean name
063     private HashMap<String, ManagedBean>   _mbeansMap    = new HashMap<String, ManagedBean>();
064     // Map containing MBeanInfo for all mbeans and mapped with unique mbean name 
065     private HashMap<String, MBeanInfo>     _mbeanInfoMap = new HashMap<String, MBeanInfo>();
066     // Map containing attribute model for all mbeans and mapped with unique mbean name
067     private HashMap<String, ManagedAttributeModel>    _attributeModelMap = new HashMap<String, ManagedAttributeModel>();
068     // Map containing operation model for all mbeans and mapped with unique mbean name
069     private HashMap<String, OperationDataModel>       _operationModelMap = new HashMap<String, OperationDataModel>();
070     // Map containing NotificationInfo for all mbeans and mapped with unique mbean name
071     private HashMap<String, List<NotificationInfoModel>> _notificationInfoMap = new HashMap<String, List<NotificationInfoModel>>();
072     // Map containing all notifications sent for all mbeans, which are registered for notification
073     private HashMap<String, List<NotificationObject>> _notificationsMap  = new HashMap<String, List<NotificationObject>>();
074     // For mbeans which have subscribed for a notification type
075     // mbean unique name mapped with notification map. Notification map contains list of notification type
076     // mapped with notification name. Notification type list contains those notification types,
077     // which are subscribed for notification.
078     private HashMap<String, HashMap<String, List<String>>> _subscribedNotificationMap = new HashMap<String, HashMap<String, List<String>>>();
079     
080     // listener for registration or unregistratioj of mbeans on mbean server
081     private ClientNotificationListener _notificationListener = null;
082     // listener for server connection. Receives notification if server connection goes down
083     private ClientListener _clientListener = null;
084     
085     public JMXServerRegistry(ManagedServer serverthrows Exception
086     {
087         super(server);
088         
089         _jmxc = JMXConnnectionFactory.getJMXConnection(
090                 ApplicationRegistry.timeout, server.getHost(),
091                 server.getPort(), server.getUser(), server.getPassword());
092         
093         _mbsc = _jmxc.getMBeanServerConnection();
094 
095         _clientListener = new ClientListener(server);
096         _notificationListener = new ClientNotificationListener(server);
097 
098         _jmxc.addConnectionNotificationListener(_clientListener, null, null);
099         _serverObjectName = new ObjectName("JMImplementation:type=MBeanServerDelegate");
100         _mbsc.addNotificationListener(_serverObjectName, _clientListener, null, null);
101 
102     }
103 
104     public MBeanServerConnection getServerConnection()
105     {
106         return _mbsc;
107     }
108 
109 
110     public String getSecurityMechanism()
111     {
112         return _securityMechanism;
113     }
114 
115     /**
116      * removes all listeners from the mbean server. This is required when user
117      * disconnects the Qpid server connection
118      */
119     public void closeServerConnection() throws Exception
120     {
121         try
122         {
123             if (_jmxc != null && _clientListener != null)
124                 _jmxc.removeConnectionNotificationListener(_clientListener);
125 
126             if (_mbsc != null && _clientListener != null)
127                 _mbsc.removeNotificationListener(_serverObjectName, _clientListener);
128 
129             // remove mbean notification listeners
130             for (String mbeanName : _subscribedNotificationMap.keySet())
131             {
132                 _mbsc.removeNotificationListener(new ObjectName(mbeanName), _notificationListener);
133             }
134         }
135         catch (ListenerNotFoundException ex)
136         {
137             MBeanUtility.printOutput(ex.toString());
138         }
139     }
140     
141     public ManagedBean getManagedObject(String uniqueName)
142     {
143         return _mbeansMap.get(uniqueName);
144     }
145     
146     public void addManagedObject(ManagedBean mbean)
147     {
148         if (mbean.isQueue())
149         {
150             addQueueMBean(mbean);
151         }
152         else if (mbean.isExchange())
153         {
154             addExchangeMBean(mbean);
155         }
156         else if (mbean.isConnection())
157         {
158             addConnectionMBean(mbean);
159         }
160         
161         addVirtualHost(mbean.getVirtualHostName());
162         _mbeansMap.put(mbean.getUniqueName(), mbean);
163     }
164 
165     public void removeManagedObject(ManagedBean mbean)
166     {
167         MBeanUtility.printOutput("Removing MBean:" + mbean.getUniqueName());
168         
169         if (mbean.isQueue())
170         {
171             removeQueueMBean(mbean);
172         }
173         else if (mbean.isExchange())
174         {
175             removeExchangeMBean(mbean);
176         }
177         else if (mbean.isConnection())
178         {
179             removeConnectionMBean(mbean);
180         }
181         
182         _mbeansMap.remove(mbean.getUniqueName());
183     }
184     
185     public void putMBeanInfo(ManagedBean mbean, MBeanInfo mbeanInfo)
186     {
187         _mbeanInfoMap.put(mbean.getUniqueName(), mbeanInfo);
188     }    
189     public MBeanInfo getMBeanInfo(ManagedBean mbean)
190     {
191         return _mbeanInfoMap.get(mbean.getUniqueName());
192     }
193     
194     public List<ManagedBean> getMBeans()
195     {
196         return new ArrayList<ManagedBean>(_mbeansMap.values());
197     }
198     
199     public void setNotificationInfo(ManagedBean mbean, List<NotificationInfoModel>value)
200     {
201         _notificationInfoMap.put(mbean.getUniqueName(), value);
202     }
203     
204     public List<NotificationInfoModel> getNotificationInfo(ManagedBean mbean)
205     {
206         return _notificationInfoMap.get(mbean.getUniqueName());
207     }
208     
209     public void addNotification(ObjectName objName, Notification notification)
210     {
211         List<NotificationObject> list = _notificationsMap.get(objName.toString());
212         NotificationObject obj = new NotificationObject(notification.getSequenceNumber(),
213                                                         new Date(notification.getTimeStamp()),
214                                                         notification.getMessage(),
215                                                         notification.getSource(),
216                                                         notification.getType());
217         
218         if (list == null)
219         {
220             list = new ArrayList<NotificationObject>();
221             _notificationsMap.put(objName.toString(), list);
222         }
223         
224         list.add(obj);
225     }
226     
227     /**
228      * Returns all the notification objects for a given mbean. If mbean is null, it returns
229      * notification objects for all the mbeans.
230      */
231     public List<NotificationObject> getNotifications(ManagedBean mbean)
232     {
233         if (mbean == null)
234         {
235             List<NotificationObject> totalList = new ArrayList<NotificationObject>();
236             for (List<NotificationObject> list : _notificationsMap.values())
237             {
238                 totalList.addAll(list);
239             }
240             return totalList;
241         }
242         else
243         {
244             return _notificationsMap.get(mbean.getUniqueName());
245         }
246     }
247     
248     public void clearNotifications(ManagedBean mbean, List<NotificationObject> list)
249     {
250         if (mbean == null)
251         {
252             if (list == null || list.isEmpty())
253             {
254                 // All notifications of all mbeans to be cleared
255                 _notificationsMap.clear();
256             }
257             else
258             {
259                 // Clear the selected notifications
260                 for (NotificationObject obj : list)
261                 {
262                     mbean = _mbeansMap.get(obj.getSource().toString());
263                     List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
264                     if (nList != null && !nList.isEmpty())
265                     {
266                         nList.remove(obj);
267                     }
268                 }
269             }
270         }
271         else 
272         {
273             if (list == null || list.isEmpty())
274             {
275                 // All notifications of this mbean to be cleared
276                 List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
277                 if (nList != null && !nList.isEmpty())
278                 {
279                     nList.clear();
280                 }
281             }
282             else
283             {
284                 // Clear the selected notifications
285                 for (NotificationObject obj : list)
286                 {
287                     List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
288                     if (nList != null && !nList.isEmpty())
289                     {
290                         nList.remove(obj);
291                     }
292                 }
293             }
294         }
295     }
296     
297     
298     
299     /**
300      * Adds notification name and type to the map. The map contains all the notification names,
301      * subscribed for an mbean.
302      @param mbean
303      @param name
304      @param type
305      */
306     public void addNotificationListener(ManagedBean mbean, String name, String type)
307     {
308         // Get the subscribed notifications map for given mbean. If map is null then create a new one. 
309         HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
310         if (map == null)
311         {
312             map = new HashMap<String, List<String>>();
313             _subscribedNotificationMap.put(mbean.getUniqueName(),map);
314         }
315         
316         // Get the list of notification types for given notification name. If null, then create a new list.
317         List<String> list = map.get(name);
318         if (list == null)
319         {
320             list = new ArrayList<String>();
321             map.put(name, list);
322         }
323         // Now add the notification type to the list
324         if (ALL.equals(type))
325         {
326             List<NotificationInfoModel> infoList = _notificationInfoMap.get(mbean.getUniqueName());
327             for (NotificationInfoModel model : infoList)
328             {                
329                 if (model.getName().equals(name))
330                 {
331                     String[] types = model.getTypes();
332                     for (int i = 0; i < types.length; i++)
333                     {
334                         list.add(types[i]);
335                     }
336                 }
337             }
338         }
339         else
340         {
341             list.add(type);
342         }
343 
344         //System.out.println("Subscribed for notification :" + mbean.getUniqueName());
345     }
346     
347     /**
348      * Checks if the given notification name and type are subscribed for the mbean.
349      */
350     public boolean hasSubscribedForNotifications(ManagedBean mbean, String name, String type)
351     {
352         if (_subscribedNotificationMap.containsKey(mbean.getUniqueName()))
353         {
354             HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
355             if (map.containsKey(name))
356             {
357                 if (map.get(name).contains(type))
358                 {
359                     return true;
360                 }
361             }
362         }
363         return false;
364     }
365     
366     /**
367      * Clears the notification name and type information from the subscribed notifications map
368      * and removes the listener from mbeanserver connection
369      @param mbean
370      @param name
371      @param type
372      @throws Exception
373      */
374     public void removeNotificationListener(ManagedBean mbean, String name, String typethrows Exception
375     {
376         //System.out.println("Removed notification listener :" + mbean.getUniqueName() + name +type);
377         if (_subscribedNotificationMap.containsKey(mbean.getUniqueName()))
378         {            
379             // get the notifications map. This map contains the notification name mapped with the notification types
380             HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
381             if (map.containsKey(name))
382             {
383                 if (ALL.equals(type))
384                 {
385                     map.remove(name);
386                 }
387                 else if (type != null)
388                 {
389                     map.get(name).remove(type);
390                     if (map.get(name).isEmpty())
391                     {
392                         map.remove(name);
393                     }
394                 }
395             }
396             if (map.size() == 0)
397             {
398                 _subscribedNotificationMap.remove(mbean.getUniqueName());
399             }
400             
401             JMXManagedObject jmxbean = (JMXManagedObject)mbean;
402             _mbsc.removeNotificationListener(jmxbean.getObjectName(), _notificationListener);
403         }
404     }
405     
406     /**
407      * When the mbean registration request is received from the mbean server, then the client listener
408      * can use this method.  It will add the mbean to a list, which will be used to add the mbean to
409      * the registry and gui
410      @param objName
411      */
412     public void registerManagedObject(ObjectName objName)
413     {
414         JMXManagedObject managedObject = new JMXManagedObject(objName);       
415         managedObject.setServer(getManagedServer());
416         addManagedObject(managedObject);
417     }
418     
419     /**
420      * When mbean unregistration notification is received from the mbean server, then client listener
421      * can invoke this method. It will add the mbean to the list of mbeans to be removed from registry
422      @param objName
423      */
424     public void unregisterManagedObject(ObjectName objName)
425     {
426         ManagedBean mbean = _mbeansMap.get(objName.toString());
427         removeManagedObject(mbean);
428         // Check if mbean was not available in the map. It can happen if mbean unregistration
429         // notification is received and the mbean is not added in the map.
430         if (mbean != null)
431         {
432             _mbeansToBeRemoved.add(mbean);
433         }
434     }
435 
436     public List<ManagedBean> getObjectsToBeRemoved()
437     {
438         if (_mbeansToBeRemoved.isEmpty())
439             return null;
440         else
441         {
442             List<ManagedBean> list = new CopyOnWriteArrayList<ManagedBean>(_mbeansToBeRemoved);
443             _mbeansToBeRemoved.clear();
444             return list;
445         }
446     }   
447     
448     public void setAttributeModel(ManagedBean mbean, ManagedAttributeModel value)
449     {
450         _attributeModelMap.put(mbean.getUniqueName(), value);
451     }
452     
453     public ManagedAttributeModel getAttributeModel(ManagedBean mbean)
454     {
455         return _attributeModelMap.get(mbean.getUniqueName());
456     }
457     
458     public void setOperationModel(ManagedBean mbean, OperationDataModel value)
459     {
460         _operationModelMap.put(mbean.getUniqueName(), value);
461     }
462     
463     public OperationDataModel getOperationModel(ManagedBean mbean)
464     {
465         return _operationModelMap.get(mbean.getUniqueName());
466     }
467     
468     public List<String> getQueueNames(String virtualHostName)
469     {
470         List<ManagedBean> list = getQueues(virtualHostName);
471         if (list == null)
472             return null;
473         
474         List<String> queueNames = new ArrayList<String>();
475         for (ManagedBean mbean : list)
476         {
477             queueNames.add(mbean.getName());
478         }
479         return queueNames;
480     }
481     
482     public String[] getExchangeNames(String virtualHostName)
483     {
484         List<ManagedBean> list = getExchanges(virtualHostName);
485         if (list == null)
486             return null;
487         
488         String[] exchanges = new String[list.size()];
489         int i = 0;
490         for (ManagedBean mbean : list)
491         {
492             exchanges[i++= mbean.getName();
493         }
494         return exchanges;
495     }
496     
497     public String[] getConnectionNames(String virtualHostName)
498     {
499         List<ManagedBean> list = getExchanges(virtualHostName);
500         if (list == null)
501             return null;
502         
503         String[] connections = new String[list.size()];
504         int i = 0;
505         for (ManagedBean mbean : list)
506         {
507             connections[i++= mbean.getName();
508         }
509         return connections;
510     }
511     
512     public void setUserList(List<String> list)
513     {
514         _usersList = list;
515         Collections.sort(_usersList);
516     }
517     
518     public List<String> getUsernames()
519     {
520         return _usersList;
521     }
522 
523     public ClientNotificationListener getNotificationListener()
524     {
525         return _notificationListener;
526     }
527 
528     public ClientListener getClientListener()
529     {
530         return _clientListener;
531     }
532 }