1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
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 }