View Javadoc

1   /* JmxUtils
2    * 
3    * Created on May 18, 2005
4    *
5    * Copyright (C) 2005 Internet Archive.
6    * 
7    * This file is part of the Heritrix web crawler (crawler.archive.org).
8    * 
9    * Heritrix is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser Public License as published by
11   * the Free Software Foundation; either version 2.1 of the License, or
12   * any later version.
13   * 
14   * Heritrix is distributed in the hope that it will be useful, 
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU Lesser Public License
20   * along with Heritrix; if not, write to the Free Software
21   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22   */
23  package org.archive.util;
24  
25  import java.net.InetSocketAddress;
26  import java.util.Arrays;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.logging.Level;
31  import java.util.logging.Logger;
32  
33  import javax.management.MBeanAttributeInfo;
34  import javax.management.MBeanOperationInfo;
35  import javax.management.MBeanParameterInfo;
36  import javax.management.MBeanServer;
37  import javax.management.MalformedObjectNameException;
38  import javax.management.ObjectName;
39  import javax.management.RuntimeOperationsException;
40  import javax.management.openmbean.CompositeType;
41  import javax.management.openmbean.InvalidOpenTypeException;
42  import javax.management.openmbean.OpenDataException;
43  import javax.management.openmbean.OpenMBeanAttributeInfo;
44  import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
45  import javax.management.openmbean.OpenMBeanOperationInfo;
46  import javax.management.openmbean.OpenMBeanOperationInfoSupport;
47  import javax.management.openmbean.OpenMBeanParameterInfo;
48  import javax.management.openmbean.OpenMBeanParameterInfoSupport;
49  import javax.management.openmbean.OpenType;
50  import javax.management.openmbean.SimpleType;
51  
52  
53  /***
54   * Static utility used by JMX.
55   * @author stack
56   * @version $Date: 2005-12-15 00:35:44 +0000 (Thu, 15 Dec 2005) $, $Revision: 4022 $
57   */
58  public class JmxUtils {
59      private static final Logger LOGGER =
60          Logger.getLogger(JmxUtils.class.getName());
61      public static final String TYPE = "type";
62      public static final String SERVICE = "CrawlService";
63      public static final String JOB = SERVICE + ".Job";
64      public static final String NAME = "name";
65      public static final String HOST = "host";
66      public static final String JMX_PORT = "jmxport";
67      public static final String GUI_PORT = "guiport";
68      public static final String KEY = "key";
69  
70      /***
71       * Key for name of the Heritrix instance hosting a Job: i.e. the
72       * CrawlJob's host/'mother'.
73       */
74      public static final String MOTHER = "mother";
75  
76      public static final ObjectName MBEAN_SERVER_DELEGATE;
77      static {
78          try {
79              MBEAN_SERVER_DELEGATE = new ObjectName(
80                  "JMImplementation:type=MBeanServerDelegate");
81          } catch (Exception e) {
82              e.printStackTrace();
83              throw new RuntimeException(e);
84          }
85      }
86      
87      private static final List OPENTYPES =
88          Arrays.asList(OpenType.ALLOWED_CLASSNAMES);
89      
90      protected JmxUtils() {
91          super();
92      }
93      
94      /***
95       * Return a string suitable for logging on registration.
96       * @param mbeanName Mbean that got registered.
97       * @param mbeanServer Server we were registered to.
98       * @param registrationDone Whether we registered successfully or not.
99       * @return String suitable for logging.
100      */
101     public static String getLogRegistrationMsg(final String mbeanName,
102             final MBeanServer mbeanServer, final boolean registrationDone) {
103         return mbeanName + (registrationDone? " " : " NOT ") +
104             "registered to " + JmxUtils.getServerDetail(mbeanServer);
105     }
106     
107     public static String getLogUnregistrationMsg(final String mbeanName,
108             final MBeanServer mbeanServer) {
109         return mbeanName + " unregistered from " +
110             JmxUtils.getServerDetail(mbeanServer);
111     }
112     
113     public static String getServerDetail(final MBeanServer server) {
114         ObjectName delegateName = null;
115         try {
116             delegateName = new ObjectName(
117                     "JMImplementation:type=MBeanServerDelegate");
118         } catch (MalformedObjectNameException e) {
119             LOGGER.log(Level.SEVERE, "Failed to create ObjectName for " +
120                     "JMImplementation:type=MBeanServerDelegate", e);
121             return null;
122         }
123         StringBuffer buffer = new StringBuffer("MBeanServerId=");
124         try {
125             buffer.append((String) server.getAttribute(delegateName,
126                     "MBeanServerId"));
127             buffer.append(", SpecificationVersion=");
128             buffer.append((String) server.getAttribute(delegateName,
129                     "SpecificationVersion"));
130             buffer.append(", ImplementationVersion=");
131             buffer.append((String) server.getAttribute(delegateName,
132                     "ImplementationVersion"));
133             buffer.append(", SpecificationVendor=");
134             buffer.append((String) server.getAttribute(delegateName,
135                     "SpecificationVendor"));
136         } catch (Exception e) {
137             LOGGER.log(Level.SEVERE, "Failed gettting server detail for " +
138                     "JMImplementation:type=MBeanServerDelegate", e);
139         }
140         return buffer.toString();
141     }
142     
143     /***
144      * @param operationName
145      *            Name of operation we're checking params on (Used in exception
146      *            if one thrown).
147      * @param params
148      *            Amount of params passed.
149      * @param count
150      *            Count of params expected.
151      */
152     public static void checkParamsCount(String operationName, Object[] params,
153             int count) {
154         if ((params.length != count)) {
155             throw new RuntimeOperationsException(
156                 new IllegalArgumentException(
157                   "Cannot invoke " + operationName + ": Passed " +
158                   Integer.toString(params.length) + " argument(s) " +
159                   "but expected " + Integer.toString(count)),
160                   "Wrong number of arguments passed: unable to invoke " +
161                   operationName + " method");
162         } 
163     }
164     
165     /***
166      * @param in MBeanOperation to convert.
167      * @return An OpenMBeanOperation version of the passed MBeanOperation.
168      */
169     public static OpenMBeanOperationInfo convertToOpenMBeanOperation(
170             MBeanOperationInfo in) {
171         return convertToOpenMBeanOperation(in, null, null);
172     }
173     
174     /***
175      * @param in MBeanOperation to convert.
176      * @param prefix A prefix to add to the name of new operation.
177      * @param returnType Return type to use in new operation.  Use this
178      * parameter to override the passed <code>in</code> return type.
179      * @return An OpenMBeanOperation version of the passed MBeanOperation.
180      */   
181     public static OpenMBeanOperationInfo convertToOpenMBeanOperation(
182             final MBeanOperationInfo in, final String prefix,
183             final OpenType returnType) {
184         MBeanParameterInfo [] params = in.getSignature();
185         OpenMBeanParameterInfo [] signature =
186             new OpenMBeanParameterInfo[params.length];
187         for (int i = 0; i < params.length; i++) {
188             signature[i] = convertToOpenMBeanOperationInfo(params[i]);
189         }
190         return new OpenMBeanOperationInfoSupport(
191                 ((prefix != null)? prefix + in.getName(): in.getName()),
192                 in.getDescription(), signature,
193                 (returnType != null)?
194                         returnType: getOpenType(in.getReturnType()),
195                 convertImpact(in.getImpact()));
196     }
197     
198     public static int convertImpact(final int impact) {
199         if (impact != MBeanOperationInfo.ACTION &&
200                 impact != MBeanOperationInfo.ACTION_INFO &&
201                 impact != MBeanOperationInfo.INFO) {
202             // Don't allow back MBeanOperationInfo.UNKNOWN impact.
203             return MBeanOperationInfo.ACTION_INFO;
204         }
205         return impact;
206     }
207     
208     /***
209      * @param in MBeanParameterInfo to convert to an OpenMBeanParameterInfo.
210      * @return OpenMBeanParameterInfo version of <code>in</code>
211      */
212     public static OpenMBeanParameterInfo
213             convertToOpenMBeanOperationInfo(MBeanParameterInfo in) {
214         return new OpenMBeanParameterInfoSupport(in.getName(),
215                 in.getDescription(), getOpenType(in.getType())); 
216     }
217     
218     public static boolean isOpenType(final Class c) {
219         return isOpenType(c.getName());
220     }
221     
222     public static boolean isOpenType(final String classname) {
223         return OPENTYPES.contains(classname);
224     }
225 
226     /***
227      * @param classString Java class name.
228      * @return Its OpenType equivalent.
229      */
230     public static OpenType getOpenType(final String classString) {
231         return getOpenType(classString, null);
232     }
233     
234     /***
235      * @param classString Java class name.
236      * @param defaultType If no equivalent found, use passed defaultType.
237      * @return Its OpenType equivalent.
238      */
239     public static OpenType getOpenType(String classString,
240             final OpenType defaultType) {
241         if (classString.equals("void")) {
242             return SimpleType.VOID;
243         }
244         if (!isOpenType(classString)) {
245             throw new InvalidOpenTypeException(classString);
246         }
247         if (classString.equals(String.class.getName())) {
248             return SimpleType.STRING;
249         } else if (classString.equals(Boolean.class.getName())) {
250             return SimpleType.BOOLEAN;
251         } else if (classString.equals(Long.class.getName())) {
252             return SimpleType.LONG;
253         } else if (classString.equals(Integer.class.getName())) {
254             return SimpleType.INTEGER;
255         } else if (classString.equals(Float.class.getName())) {
256             return SimpleType.FLOAT;
257         } else if (classString.equals(Double.class.getName())) {
258             return SimpleType.DOUBLE;
259         } else if (defaultType != null) {
260             return defaultType;
261         }
262         throw new RuntimeException("Unsupported type: " + classString);
263     }
264    
265     /***
266      * @param in AttributeInfo to convert.
267      * @return OpenMBeanAttributeInfo version of <code>in</code>.
268      */
269     public static OpenMBeanAttributeInfo
270     convertToOpenMBeanAttribute(MBeanAttributeInfo in) {
271         return convertToOpenMBeanAttribute(in, null);
272     }
273 
274     /***
275      * @param in AttributeInfo to convert.
276      * @param prefix Prefix to add to names of new attributes. If null, nothing
277      * is added.
278      * @return OpenMBeanAttributeInfo version of <code>in</code>.
279      */
280     public static OpenMBeanAttributeInfo
281             convertToOpenMBeanAttribute(final MBeanAttributeInfo in,
282                     final String prefix) {
283         return createOpenMBeanAttributeInfo(getOpenType(in.getType()), in,
284                 prefix);
285     }
286     
287     /***
288      * @param type Type of new OpenMBeanAttributeInfo.
289      * @param in The MBeanAttributeInfo we're converting.
290      * @param prefix Prefix to add to name of new Attribute (If null, nothing
291      * is added).
292      * @return New OpenMBeanAttributeInfo based on <code>in</code>.
293      */
294     public static OpenMBeanAttributeInfo createOpenMBeanAttributeInfo(
295             final OpenType type, final MBeanAttributeInfo in,
296             final String prefix) {
297         return new OpenMBeanAttributeInfoSupport(
298                 ((prefix != null)? prefix + in.getName(): in.getName()),
299                 in.getDescription(), type, in.isReadable(),
300                 in.isWritable(), in.isIs());
301     }
302     
303     /***
304      * @param m A map to make a CompositeType of (Assumption is that order does
305      * not matter. If it does, pass a map of sorted keys).
306      * @param compositeTypeName Name to give created compositeType.
307      * @param compositeTypeDescription Description.
308      * @return CompositeType made by examination of passed TreeMap.
309      * @throws OpenDataException
310      */
311     public static CompositeType createCompositeType(final Map m,
312             final String compositeTypeName,
313             final String compositeTypeDescription)
314     throws OpenDataException {
315         String [] keys = new String[m.size()];
316         OpenType [] types = new OpenType[m.size()];
317         int index = 0;
318         for (final Iterator i = m.keySet().iterator(); i.hasNext();) {
319             String key = (String)i.next();
320             keys[index] = key;
321             types[index] = getOpenType(m.get(key).getClass().getName());
322             index++;
323         }
324         return new CompositeType(compositeTypeName, compositeTypeDescription,
325             keys, keys, types);
326     }
327 
328     public static InetSocketAddress extractAddress(final ObjectName name) {
329         return new InetSocketAddress(name.getKeyProperty(HOST),
330             Integer.parseInt(name.getKeyProperty(JMX_PORT)));
331     }
332 
333     /***
334      * Returns the UID portion of the name key property of
335      * an object name representing a "CrawlService.Job" bean.
336      * It is assumed that the name will have the format
337      * {crawl name}-{uid}.
338      * @param on A CrawlServer.Job object name.
339      * @return Uid for a CrawlServer.Job.
340      */
341     public static String getUid(final ObjectName on) {
342         String name = on.getKeyProperty(NAME);
343         return name.substring(name.indexOf("-") + 1);
344     }
345 }