MBeanUtility.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 java.math.BigInteger;
024 import java.util.ArrayList;
025 import java.util.Arrays;
026 import java.util.Iterator;
027 import java.util.List;
028 import java.util.Set;
029 
030 import javax.management.Attribute;
031 import javax.management.AttributeList;
032 import javax.management.InstanceNotFoundException;
033 import javax.management.JMException;
034 import javax.management.MBeanAttributeInfo;
035 import javax.management.MBeanException;
036 import javax.management.MBeanInfo;
037 import javax.management.MBeanNotificationInfo;
038 import javax.management.MBeanOperationInfo;
039 import javax.management.MBeanServerConnection;
040 import javax.management.ObjectInstance;
041 import javax.management.ObjectName;
042 import javax.management.ReflectionException;
043 
044 import org.apache.qpid.management.ui.ApplicationRegistry;
045 import org.apache.qpid.management.ui.ManagedBean;
046 import org.apache.qpid.management.ui.ManagedServer;
047 import org.apache.qpid.management.ui.exceptions.ManagementConsoleException;
048 import org.apache.qpid.management.ui.model.AttributeData;
049 import org.apache.qpid.management.ui.model.ManagedAttributeModel;
050 import org.apache.qpid.management.ui.model.NotificationInfoModel;
051 import org.apache.qpid.management.ui.model.OperationData;
052 import org.apache.qpid.management.ui.model.OperationDataModel;
053 import org.apache.qpid.management.ui.model.ParameterData;
054 import org.apache.qpid.management.ui.views.ViewUtility;
055 
056 /**
057  * Utility class for all mbeanserver related operations. Keeps all JMX code out from view and model classes
058  @author Bhupendra Bhardwaj
059  */
060 public class MBeanUtility
061 {
062     public static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
063     public static final BigInteger MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE);
064     /**
065      * Retrieves the MBeanInfo from MBeanServer and stores in the application registry
066      @param mbean  managed bean
067      @return MBeanInfo
068      @throws Exception, if server connection is null or if server throws Exception
069      */
070     public static MBeanInfo getMBeanInfo(ManagedBean mbeanthrows Exception
071     {
072         ManagedServer server = mbean.getServer();
073         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
074 
075         MBeanServerConnection mbsc = serverRegistry.getServerConnection();
076         if (mbsc == null)
077         {
078             throw new ManagementConsoleException("Server connection is broken");
079         }
080         
081         JMXManagedObject jmxbean = (JMXManagedObject)mbean;
082         MBeanInfo mbeanInfo = mbsc.getMBeanInfo(jmxbean.getObjectName());
083         serverRegistry.putMBeanInfo(mbean, mbeanInfo);
084         
085         // populate the server registry with attribute and operation info
086         getAttributes(mbean);
087         getOperations(mbean);
088         
089         return mbeanInfo;
090     }
091     
092     /**
093      * executes the MBean operation
094      @param mbean
095      @param opData
096      @return MBean operation return value
097      @throws Exception if server connection is broken or if operation execution fails on the mbean server
098      */
099     public static Object execute(ManagedBean mbean, OperationData opDatathrows Exception
100     {
101         String opName = opData.getName();
102         Object[] values = null;
103         String[] signature = null;
104         
105         List<ParameterData> params = opData.getParameters();
106         if (params != null && !params.isEmpty())
107         {
108             signature = new String[params.size()];;
109             values = new Object[params.size()];
110             for (int i = 0; i < params.size(); i++)
111             {
112                 signature[i= params.get(i).getType();
113                 values[i= params.get(i).getValue();
114             }
115         }
116         
117         ManagedServer server = mbean.getServer();
118         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
119 
120         MBeanServerConnection mbsc = serverRegistry.getServerConnection();
121         if (mbsc == null)
122         {
123             throw new ManagementConsoleException("Server connection is broken");
124             // TODO
125             // try and get the connection again if it was disconnected
126         }
127         JMXManagedObject jmxbean = (JMXManagedObject)mbean;
128         return mbsc.invoke(jmxbean.getObjectName(), opName, values, signature);
129     }
130     
131     /**
132      @see MBeanUtility#handleException(ManagedBean, Exception)
133      */
134     public static void handleException(Exception ex)
135     {
136         handleException(null, ex);
137     }
138     
139     /**
140      * handels the exception received. Shows the exception to the user in best suitable way
141      @param mbean managed bean
142      @param ex   Exception
143      */
144     public static void handleException(ManagedBean mbean, Throwable ex)
145     {
146         if (mbean == null)
147         {
148             ViewUtility.popupErrorMessage("Error""Managed Object is null \n" + ex.toString());
149             printStackTrace(ex);
150         }
151         else if (ex instanceof ReflectionException)
152         {
153             ViewUtility.popupErrorMessage(mbean.getInstanceName()"Server has thrown error \n" + ex.toString());
154             printStackTrace(ex);
155         }
156         else if (ex instanceof InstanceNotFoundException)
157         {
158             ViewUtility.popupErrorMessage(mbean.getInstanceName()"Managed Object Not Found \n" + ex.toString());
159             printStackTrace(ex);
160         }
161         else if (ex instanceof MBeanException)
162         {
163             String cause = ((MBeanException)ex).getTargetException().getMessage();
164             if (cause == null)
165                 cause = ex.toString();
166             ViewUtility.popupInfoMessage(mbean.getInstanceName(), cause);
167         }
168         else if (ex instanceof JMException)
169         {
170             ViewUtility.popupErrorMessage(mbean.getInstanceName()"Management Exception occured \n" + ex.toString());
171         }
172         else if (ex instanceof ManagementConsoleException)
173         {
174             ViewUtility.popupErrorMessage(mbean.getInstanceName(), ex.getMessage());
175         }
176         else if (ex instanceof SecurityException)
177         {
178             ViewUtility.popupErrorMessage(mbean.getInstanceName(), ex.getMessage());
179         }
180         else 
181         {
182             if (ex.getCause() != null)
183             {
184                 handleException(mbean, ex.getCause());
185             }
186             else
187             {
188                 String msg = ex.getMessage();
189                 if (msg == null)
190                 {
191                     msg = ex.toString();
192                 }
193                 ViewUtility.popupErrorMessage(mbean.getInstanceName(), msg);
194                 printStackTrace(ex);
195             }
196         }
197         
198     }
199     
200     /**
201      * Registers the notification listener with the MBeanServer
202      @param mbean   managed bean
203      @param name    notification name
204      @param type    notification type
205      @throws Exception  if server connection is broken or if listener could not be created 
206      */
207     public static void createNotificationlistener(ManagedBean mbean, String name, String type)
208         throws Exception
209     {
210         JMXManagedObject jmxbean = (JMXManagedObject)mbean;
211         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
212         serverRegistry.addNotificationListener(mbean, name, type);
213         MBeanServerConnection mbsc = serverRegistry.getServerConnection();
214         
215         if (mbsc == null)
216         {
217             throw new ManagementConsoleException("Server connection is broken");
218         }
219         mbsc.addNotificationListener(jmxbean.getObjectName(), serverRegistry.getNotificationListener(), null, null);
220     }
221     
222     public static void removeNotificationListener(ManagedBean mbean, String name, String typethrows Exception
223     {
224         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
225         serverRegistry.removeNotificationListener(mbean, name, type);
226     }
227     
228     /**
229      * Checks if the server registry contains attribute information for this mbean. If not then it queries the
230      * mbean server for complete mbean information, else it gets the latest value of the given attribute
231      * from mbean server.
232      @return attribute data for the given mbean attribute
233      */
234     public static AttributeData getAttributeData(ManagedBean mbean, String attributethrows Exception
235     {
236         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
237         ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
238         if (attributeModel == null)
239         {
240             // If process is here, it means the mbeanInfo is not retrieved from mbean server even once for this mbean
241             getMBeanInfo(mbean);
242         }
243         else
244         {
245             // refresh attribute value from mbean server
246             refreshAttribute(mbean, attribute);
247         }
248         attributeModel = serverRegistry.getAttributeModel(mbean);
249         return attributeModel.getAttribute(attribute);
250     }
251     
252     /**
253      * Retrieves the latest attribute value from mbean server for the given mbean attribute
254      * and also sets that value in the attribute model in the server registry
255      @return latest attribute value for the given mbean attribute
256      */
257     public static Object refreshAttribute(ManagedBean mbean, String attributethrows Exception
258     {
259         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
260         MBeanServerConnection mbsc = serverRegistry.getServerConnection();
261         
262         if (mbsc == null)
263         {
264             throw new ManagementConsoleException("Server connection is broken");
265         }
266         
267         Object value = mbsc.getAttribute(((JMXManagedObject)mbean).getObjectName(), attribute);
268         // update the attribute data in server registry for this attribute
269         ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
270         attributeModel.setAttributeValue(attribute, value);
271         return value;
272     }
273     
274     /**
275      * Retrieves the attribute values from MBeanSever and stores in the server registry.
276      @param mbean
277      @return the attribute model
278      @throws Exception if attributes can not be retrieved from MBeanServer
279      */
280     public static ManagedAttributeModel getAttributes(ManagedBean mbeanthrows Exception
281     {
282         ObjectName objName = ((JMXManagedObject)mbean).getObjectName();
283         String[] attributes = null;
284         AttributeList list = null;
285         
286         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
287         MBeanServerConnection mbsc = serverRegistry.getServerConnection();
288         MBeanAttributeInfo[] attributesInfo = null;
289         ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
290         
291         if (attributeModel == null)
292         {
293             // If the process is here, then it means the attribute values are not retrieved from mbean server
294             // even once for this mbean. Create attribute model, retrieve values from mbean server and 
295             // set the attribute model in server registry for this mbean
296             attributeModel = new ManagedAttributeModel();
297             attributesInfo = serverRegistry.getMBeanInfo(mbean).getAttributes();
298             attributes = new String[attributesInfo.length];
299             for (int i = 0; i< attributesInfo.length ; i++)
300             {
301                 attributes[i= attributesInfo[i].getName();
302                 attributeModel.setAttributeDescription(attributes[i], attributesInfo[i].getDescription());
303                 attributeModel.setAttributeWritable(attributes[i], attributesInfo[i].isWritable());
304                 attributeModel.setAttributeReadable(attributes[i], attributesInfo[i].isReadable());
305             }
306         }  
307         else
308         {
309             attributes = attributeModel.getAttributeNames().toArray(new String[0]);
310         }
311         
312         if (attributes.length != 0)
313         {
314             list = mbsc.getAttributes(objName, attributes);
315             for (Iterator itr = list.iterator(); itr.hasNext();)
316             {
317                 Attribute attrib = (Attribute)itr.next();
318                 attributeModel.setAttributeValue(attrib.getName(), attrib.getValue());
319             }
320         }               
321         
322         serverRegistry.setAttributeModel(mbean, attributeModel);       
323         return attributeModel;
324     }
325     
326     /**
327      * Updates the attribute value of an MBean
328      @param mbean
329      @param attribute
330      @param value
331      @throws Exception if MBeanServer throws exception in updating the attribute value
332      */
333     public static void updateAttribute(ManagedBean mbean, AttributeData attribute, String valuethrows Exception
334     {
335         JMXManagedObject jmxbean = (JMXManagedObject)mbean;
336         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
337 
338         MBeanServerConnection mbsc = serverRegistry.getServerConnection();
339         
340         Object newValue = value;
341         if (attribute.getDataType().equals(Long.class.getName()))
342         {
343             if (MAX_LONG.compareTo(new BigInteger(value)) == -1)
344             {
345                 throw new ManagementConsoleException("Entered value is too big for \"" +
346                                                      ViewUtility.getDisplayText(attribute.getName()) "\"");
347             }
348             newValue = new Long(Long.parseLong(value));
349         }
350         else if (attribute.getDataType().equals(Integer.class.getName()))
351         {
352             if (MAX_INT.compareTo(new BigInteger(value)) == -1)
353             {
354                 throw new ManagementConsoleException("Entered value is too big for " + attribute.getName());
355             }
356             newValue = new Integer(Integer.parseInt(value));
357         }
358         
359         mbsc.setAttribute(jmxbean.getObjectName()new Attribute(attribute.getName(), newValue));           
360         // Update the value in the registry, to avoid refreshing from mbsc
361         ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
362         attributeModel.setAttributeValue(attribute.getName(), newValue);
363     }
364     
365     /**
366      * populates the operation data model in server registry for given mbean
367      @param mbean
368      @return operation data model
369      */
370     public static OperationDataModel getOperations(ManagedBean mbean)
371     {
372         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
373         OperationDataModel dataModel = serverRegistry.getOperationModel(mbean);
374         if (dataModel == null)
375         {
376             // Create operation model and set it in server registry for this mbean
377             MBeanOperationInfo[] operationsInfo = serverRegistry.getMBeanInfo(mbean).getOperations();
378             dataModel = new OperationDataModel();
379             
380             for (int i = 0; i < operationsInfo.length; i++)
381             {
382                 dataModel.addOperation(operationsInfo[i]);
383             }
384             
385             serverRegistry.setOperationModel(mbean, dataModel);
386         }
387         return dataModel;
388     }
389     
390     /**
391      * populates the notification in the server registry for given mbean
392      @param mbean
393      @return notification info model
394      */
395     public static NotificationInfoModel[] getNotificationInfo(ManagedBean mbean)
396     {
397         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
398         MBeanNotificationInfo[] info = serverRegistry.getMBeanInfo(mbean).getNotifications();
399         
400         // Check if this mbean sends any notification
401         if (info == null || info.length == 0)
402             return null;
403         
404         // Create notification model if not already set in the server registry for this mbean
405         List<NotificationInfoModel> list = serverRegistry.getNotificationInfo(mbean);
406         if (list != null
407             return list.toArray(new NotificationInfoModel[0]);
408         else
409             list = new ArrayList<NotificationInfoModel>();
410         
411         for (int i = 0; i < info.length; i++)
412         {
413             list.add(new NotificationInfoModel(info[i].getName(), info[i].getDescription(), info[i].getNotifTypes()));
414         }
415         
416         // Set the notification model in the server registry for this mbean
417         serverRegistry.setNotificationInfo(mbean, list);
418         return list.toArray(new NotificationInfoModel[0]);
419     }
420     
421     /**
422      * Retrieves all the MBeans from mbean server for a given domain
423      @return list of ManagedBeans
424      */
425     public static List<ManagedBean> getManagedObjectsForDomain(ManagedServer server, String domainthrows Exception
426     {
427         List<ManagedBean> mbeans = new ArrayList<ManagedBean>();
428         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
429         MBeanServerConnection mbsc = serverRegistry.getServerConnection();
430         ObjectName objName = new ObjectName(domain + ":*")
431         Set objectInstances = mbsc.queryMBeans(objName, null);
432 
433         for (Iterator itr = objectInstances.iterator(); itr.hasNext();)
434         {
435             ObjectInstance instance = (ObjectInstance)itr.next();
436             ManagedBean obj = new JMXManagedObject(instance.getObjectName());
437             mbeans.add(obj);
438         }
439         
440         return mbeans;
441     }
442     
443     /**
444      * Returns all the domains for the given server. This method can be removed as now this RCP is specific to 
445      * Qpid and domain is also fixed
446      */
447     public static List<String> getAllDomains(ManagedServer serverthrows Exception
448     {
449         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
450         MBeanServerConnection mbsc = serverRegistry.getServerConnection();
451         String[] domains = mbsc.getDomains();
452         return Arrays.asList(domains);
453     }
454     
455     public static void printOutput(String statement)
456     {
457         if (ApplicationRegistry.debug)
458         {
459             System.out.println(statement);
460         }
461     }
462     
463     public static void printStackTrace(Throwable ex)
464     {
465         if (ApplicationRegistry.debug)
466         {
467             ex.printStackTrace();
468         }
469     }
470 }