001    /*
002     * $Id: MBeanHelper.java,v 1.15 2014/05/18 12:25:15 oboehm Exp $
003     *
004     * Copyright (c) 2008 by Oliver Boehm
005     *
006     * Licensed under the Apache License, Version 2.0 (the "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *   http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     *
018     * (c)reated 19.02.2009 by oliver (ob@oasd.de)
019     */
020    package patterntesting.runtime.jmx;
021    
022    import java.lang.management.ManagementFactory;
023    
024    import javax.management.*;
025    import javax.management.openmbean.*;
026    
027    import org.apache.commons.lang.StringUtils;
028    import org.slf4j.*;
029    
030    /**
031     * This class simplifies the use of JMX and MBeans a little bit.
032     *
033     * @author <a href="boehm@javatux.de">oliver</a>
034     * @since 19.02.2009
035     * @version $Revision: 1.15 $
036     */
037    public class MBeanHelper {
038    
039        private static final Logger log = LoggerFactory.getLogger(MBeanHelper.class);
040        private static MBeanServer server = ManagementFactory.getPlatformMBeanServer();
041    
042        static {
043            registerMBean("patterntesting.runtime:name=Info", new Info());
044        }
045    
046        /** Utility class - no need to instantiate it */
047        private MBeanHelper() {}
048    
049        /**
050         * Gets an MBean name for the given object.
051         *
052         * @param mbean the mbean
053         *
054         * @return the name of the MBean
055         */
056        public static String getMBeanName(final Object mbean) {
057            return getMBeanName(mbean.getClass());
058        }
059    
060        /**
061         * Gets an MBean name for the given object.
062         *
063         * @param mbean the mbean
064         * @param level the level
065         * @return the name of the MBean
066         * @since 1.4.3
067         */
068        public static String getMBeanName(final Object mbean, final int level) {
069            return getMBeanName(mbean.getClass(), level);
070        }
071    
072        /**
073         * Converts the class name into a MBean name. For a hierachical structure of
074         * the registered MBeans take a look at <a href=
075         * "http://www.oracle.com/technetwork/java/javase/tech/best-practices-jsp-136021.html"
076         * >Java Management Extensions (JMX) - Best Practices</a>.
077         * <p>
078         * The default level for an MBean is since 1.4.3 now set to "2" (see
079         * {@link #getMBeanName(Object, int)}. This means you will find all MBeans
080         * from PatternTesting Runtime under the node "patterntesting.runtime"
081         * if you open your JMX console (e.g. the 'jconsole' from the JDK).
082         * </p>
083         *
084         * @param cl e.g. my.good.bye.World
085         * @return a valid MBean name e.g. "my:type=good,good=bye,name=World"
086         * @see #getMBeanName(Class, int)
087         */
088        public static String getMBeanName(final Class<?> cl) {
089            return getMBeanName(cl, 2);
090        }
091    
092        /**
093         * Converts the class name into a MBean name. For a hierachical structure of
094         * the registered MBeans take a look at <a href=
095         * "http://www.oracle.com/technetwork/java/javase/tech/best-practices-jsp-136021.html"
096         * >Java Management Extensions (JMX) - Best Practices</a>.
097         * <p>
098         * With the 2nd parameter (level) you can control the root element. If you
099         * set it i.e. to 2 the result in the jconsole would look like:
100         * <pre>
101         * my.good
102         *     bye
103         *         World
104         * </pre>
105         * if the given class is "my.good.by.World".
106         * </p>
107         *
108         * @param cl e.g. my.good.bye.World
109         * @param level the level, e.g.
110         * @return a valid MBean name e.g. "my.good:type=bye,name=World"
111         * @since 1.4.3
112         */
113        public static String getMBeanName(final Class<?> cl, final int level) {
114            assert level > 0 : "level must be 1 or greater";
115            String packageName = cl.getPackage().getName();
116            String[] names = StringUtils.split(packageName, ".");
117            int n = (level >= names.length) ? names.length - 1 : level;
118            String domain = names[0];
119            for (int i = 1; i < n; i++) {
120                domain += "." + names[i];
121            }
122            String type = names[n];
123            StringBuffer mbeanName = new StringBuffer(domain + ":type=" + type);
124            for (int i = n+1; i < names.length; i++) {
125                mbeanName.append("," + names[i-1] + "=" + names[i]);
126            }
127            return mbeanName + ",name=" + cl.getSimpleName();
128        }
129    
130        /**
131         * Register the given object as MBean.
132         *
133         * @param mbean the mbean
134         *
135         * @throws JMException if registration fails
136         */
137        public static void registerMBean(final Object mbean) throws JMException {
138            String mbeanName = getMBeanName(mbean);
139            registerMBean(mbeanName, mbean);
140        }
141    
142        /**
143         * Register the given object as MBean.
144         *
145         * @param mbeanName the mbean name
146         * @param mbean the mbean
147         */
148        public static synchronized void registerMBean(final String mbeanName, final Object mbean) {
149            try {
150                ObjectName name = new ObjectName(mbeanName);
151                registerMBean(name, mbean);
152            } catch (MalformedObjectNameException e) {
153                log.info("can't register <" + mbean + "> as MBean", e);
154            }
155        }
156    
157        /**
158         * Register m bean.
159         *
160         * @param name the name
161         * @param mbean the mbean
162         */
163        public static synchronized void registerMBean(final ObjectName name, final Object mbean) {
164            try {
165                log.trace("registering " + name + "...");
166                server.registerMBean(mbean, name);
167                log.debug(name + " successful registered as MBean");
168            } catch (Exception e) {
169                log.info("can't register <" + mbean + "> as MBean", e);
170            }
171        }
172    
173        /**
174         * Unregister m bean.
175         *
176         * @param mbeanName the mbean name
177         */
178        public static synchronized void unregisterMBean(final String mbeanName) {
179            try {
180                ObjectName name = new ObjectName(mbeanName);
181                server.unregisterMBean(name);
182                log.debug("MBean " + name + " successful unregistered");
183            } catch (Exception e) {
184                log.info("can't unregister " + mbeanName, e);
185            }
186        }
187    
188        /**
189         * Checks if is registered.
190         *
191         * @param mbeanName the mbean name
192         *
193         * @return true, if is registered
194         */
195        public static boolean isRegistered(final String mbeanName) {
196            try {
197                ObjectName name = new ObjectName(mbeanName);
198                ObjectInstance mbean = server.getObjectInstance(name);
199                return (mbean != null);
200            } catch (Exception e) {
201                log.trace(mbeanName + " not found (" + e + ")");
202                return false;
203            }
204        }
205    
206        /**
207         * Checks if is registered.
208         *
209         * @param obj the obj
210         *
211         * @return true, if is registered
212         */
213        public static boolean isRegistered(final Object obj) {
214            String mbeanName = getMBeanName(obj.getClass());
215            return isRegistered(mbeanName);
216        }
217    
218        /**
219         * Gets the object instance.
220         *
221         * @param name the name
222         * @return the object instance
223         * @throws InstanceNotFoundException the instance not found exception
224         */
225        public static ObjectInstance getObjectInstance(final String name) throws InstanceNotFoundException {
226            try {
227                ObjectName mbeanName = new ObjectName(name);
228                return getObjectInstance(mbeanName);
229            } catch (MalformedObjectNameException e) {
230                throw new IllegalArgumentException(name, e);
231            }
232        }
233    
234        /**
235         * Gets the object instance.
236         *
237         * @param mbeanName the mbean name
238         * @return the object instance
239         * @throws InstanceNotFoundException the instance not found exception
240         */
241        public static ObjectInstance getObjectInstance(final ObjectName mbeanName)
242                throws InstanceNotFoundException {
243            return server.getObjectInstance(mbeanName);
244        }
245    
246        /**
247         * Gets the attribute.
248         *
249         * @param mbeanName the mbean name
250         * @param attributeName the attribute name
251         * @return the attribute
252         * @throws InstanceNotFoundException the instance not found exception
253         * @throws JMException the jM exception
254         */
255        public static Object getAttribute(final String mbeanName, final String attributeName)
256                throws InstanceNotFoundException, JMException {
257            try {
258                ObjectName mbean = new ObjectName(mbeanName);
259                return getAttribute(mbean, attributeName);
260            } catch (MalformedObjectNameException e) {
261                throw new IllegalArgumentException(mbeanName, e);
262            }
263        }
264    
265        /**
266         * Gets the attribute.
267         *
268         * @param mbean the mbean
269         * @param attributeName the attribute name
270         * @return the attribute
271         * @throws InstanceNotFoundException the instance not found exception
272         * @throws JMException the jM exception
273         */
274        public static Object getAttribute(final ObjectName mbean, final String attributeName)
275                throws InstanceNotFoundException, JMException {
276            try {
277                return server.getAttribute(mbean, attributeName);
278            } catch (AttributeNotFoundException e) {
279                throw new IllegalArgumentException(attributeName, e);
280            }
281        }
282    
283        /**
284         * Creates a {@link TabularDataSupport} object.
285         *
286         * @param rowType the row type
287         * @param itemNames the item names
288         * @return the tabular data support
289         * @throws OpenDataException the open data exception
290         */
291        public static TabularDataSupport createTabularDataSupport(final CompositeType rowType, final String[] itemNames)
292                throws OpenDataException {
293            TabularType tabularType = new TabularType("propertyTabularType",
294                    "properties tabular", rowType, itemNames);
295            TabularDataSupport data = new TabularDataSupport(tabularType);
296            return data;
297        }
298    
299    }