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 server) throws 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 type) throws 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 }
|