001/* 002 * Copyright 2009 Red Hat, Inc. 003 * Red Hat licenses this file to you under the Apache License, version 004 * 2.0 (the "License"); you may not use this file except in compliance 005 * with the License. You may obtain a copy of the License at 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * Unless required by applicable law or agreed to in writing, software 008 * distributed under the License is distributed on an "AS IS" BASIS, 009 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 010 * implied. See the License for the specific language governing 011 * permissions and limitations under the License. 012 */ 013 014package org.hornetq.api.core.management; 015 016import java.util.Collections; 017import java.util.HashMap; 018import java.util.Iterator; 019import java.util.Map; 020 021import org.hornetq.api.core.Message; 022import org.hornetq.api.core.SimpleString; 023import org.hornetq.core.logging.Logger; 024import org.hornetq.utils.json.JSONArray; 025import org.hornetq.utils.json.JSONObject; 026 027/** 028 * Helper class to use HornetQ Core messages to manage server resources. 029 * 030 * @author <a href="mailto:jmesnil@redhat.com">Jeff Mesnil</a> 031 * @author <a href="mailto:tim.fox@jboss.com">Tim Fox</a> 032 * 033 * @version <tt>$Revision$</tt> 034 */ 035public class ManagementHelper 036{ 037 // Constants ----------------------------------------------------- 038 039 private static final Logger log = Logger.getLogger(ManagementHelper.class); 040 041 public static final SimpleString HDR_RESOURCE_NAME = new SimpleString("_HQ_ResourceName"); 042 043 public static final SimpleString HDR_ATTRIBUTE = new SimpleString("_HQ_Attribute"); 044 045 public static final SimpleString HDR_OPERATION_NAME = new SimpleString("_HQ_OperationName"); 046 047 public static final SimpleString HDR_OPERATION_SUCCEEDED = new SimpleString("_HQ_OperationSucceeded"); 048 049 public static final SimpleString HDR_NOTIFICATION_TYPE = new SimpleString("_HQ_NotifType"); 050 051 public static final SimpleString HDR_NOTIFICATION_TIMESTAMP = new SimpleString("_HQ_NotifTimestamp"); 052 053 public static final SimpleString HDR_ROUTING_NAME = new SimpleString("_HQ_RoutingName"); 054 055 public static final SimpleString HDR_CLUSTER_NAME = new SimpleString("_HQ_ClusterName"); 056 057 public static final SimpleString HDR_ADDRESS = new SimpleString("_HQ_Address"); 058 059 public static final SimpleString HDR_BINDING_ID = new SimpleString("_HQ_Binding_ID"); 060 061 public static final SimpleString HDR_BINDING_TYPE = new SimpleString("_HQ_Binding_Type"); 062 063 public static final SimpleString HDR_FILTERSTRING = new SimpleString("_HQ_FilterString"); 064 065 public static final SimpleString HDR_DISTANCE = new SimpleString("_HQ_Distance"); 066 067 public static final SimpleString HDR_CONSUMER_COUNT = new SimpleString("_HQ_ConsumerCount"); 068 069 public static final SimpleString HDR_USER = new SimpleString("_HQ_User"); 070 071 public static final SimpleString HDR_CHECK_TYPE = new SimpleString("_HQ_CheckType"); 072 073 public static final SimpleString HDR_PROPOSAL_GROUP_ID = new SimpleString("_JBM_ProposalGroupId"); 074 075 public static final SimpleString HDR_PROPOSAL_VALUE = new SimpleString("_JBM_ProposalValue"); 076 077 public static final SimpleString HDR_PROPOSAL_ALT_VALUE = new SimpleString("_JBM_ProposalAltValue"); 078 079 // Attributes ---------------------------------------------------- 080 081 // Static -------------------------------------------------------- 082 083 /** 084 * Stores a resource attribute in a message to retrieve the value from the server resource. 085 * 086 * @param message message 087 * @param resourceName the name of the resource 088 * @param attribute the name of the attribute 089 * 090 * @see ResourceNames 091 */ 092 public static void putAttribute(final Message message, final String resourceName, final String attribute) 093 { 094 message.putStringProperty(ManagementHelper.HDR_RESOURCE_NAME, new SimpleString(resourceName)); 095 message.putStringProperty(ManagementHelper.HDR_ATTRIBUTE, new SimpleString(attribute)); 096 } 097 098 /** 099 * Stores a operation invocation in a message to invoke the corresponding operation the value from the server resource. 100 * 101 * @param message message 102 * @param resourceName the name of the resource 103 * @param operationName the name of the operation to invoke on the resource 104 * 105 * @see ResourceNames 106 */ 107 public static void putOperationInvocation(final Message message, 108 final String resourceName, 109 final String operationName) throws Exception 110 { 111 ManagementHelper.putOperationInvocation(message, resourceName, operationName, (Object[])null); 112 } 113 114 /** 115 * Stores a operation invocation in a message to invoke the corresponding operation the value from the server resource. 116 * 117 * @param message message 118 * @param resourceName the name of the server resource 119 * @param operationName the name of the operation to invoke on the server resource 120 * @param parameters the parameters to use to invoke the server resource 121 * 122 * @see ResourceNames 123 */ 124 public static void putOperationInvocation(final Message message, 125 final String resourceName, 126 final String operationName, 127 final Object... parameters) throws Exception 128 { 129 // store the name of the operation in the headers 130 message.putStringProperty(ManagementHelper.HDR_RESOURCE_NAME, new SimpleString(resourceName)); 131 message.putStringProperty(ManagementHelper.HDR_OPERATION_NAME, new SimpleString(operationName)); 132 133 // and the params go in the body, since might be too large for header 134 135 String paramString; 136 137 if (parameters != null) 138 { 139 JSONArray jsonArray = ManagementHelper.toJSONArray(parameters); 140 141 paramString = jsonArray.toString(); 142 } 143 else 144 { 145 paramString = null; 146 } 147 148 message.getBodyBuffer().writeNullableSimpleString(SimpleString.toSimpleString(paramString)); 149 } 150 151 private static JSONArray toJSONArray(final Object[] array) throws Exception 152 { 153 JSONArray jsonArray = new JSONArray(); 154 155 for (Object parameter : array) 156 { 157 if (parameter instanceof Map) 158 { 159 Map<String, Object> map = (Map<String, Object>)parameter; 160 161 JSONObject jsonObject = new JSONObject(); 162 163 for (Map.Entry<String, Object> entry : map.entrySet()) 164 { 165 String key = entry.getKey(); 166 167 Object val = entry.getValue(); 168 169 if (val != null) 170 { 171 if (val.getClass().isArray()) 172 { 173 val = ManagementHelper.toJSONArray((Object[])val); 174 } 175 else 176 { 177 ManagementHelper.checkType(val); 178 } 179 } 180 181 jsonObject.put(key, val); 182 } 183 184 jsonArray.put(jsonObject); 185 } 186 else 187 { 188 if (parameter != null) 189 { 190 Class clz = parameter.getClass(); 191 192 if (clz.isArray()) 193 { 194 Object[] innerArray = (Object[])parameter; 195 196 jsonArray.put(ManagementHelper.toJSONArray(innerArray)); 197 } 198 else 199 { 200 ManagementHelper.checkType(parameter); 201 202 jsonArray.put(parameter); 203 } 204 } 205 else 206 { 207 jsonArray.put((Object)null); 208 } 209 } 210 } 211 212 return jsonArray; 213 } 214 215 private static Object[] fromJSONArray(final JSONArray jsonArray) throws Exception 216 { 217 Object[] array = new Object[jsonArray.length()]; 218 219 for (int i = 0; i < jsonArray.length(); i++) 220 { 221 Object val = jsonArray.get(i); 222 223 if (val instanceof JSONArray) 224 { 225 Object[] inner = ManagementHelper.fromJSONArray((JSONArray)val); 226 227 array[i] = inner; 228 } 229 else if (val instanceof JSONObject) 230 { 231 JSONObject jsonObject = (JSONObject)val; 232 233 Map<String, Object> map = new HashMap<String, Object>(); 234 235 Iterator<String> iter = jsonObject.keys(); 236 237 while (iter.hasNext()) 238 { 239 String key = iter.next(); 240 241 Object innerVal = jsonObject.get(key); 242 243 if (innerVal instanceof JSONArray) 244 { 245 innerVal = ManagementHelper.fromJSONArray(((JSONArray)innerVal)); 246 } 247 else if (innerVal instanceof JSONObject) 248 { 249 Map<String, Object> innerMap = new HashMap<String, Object>(); 250 JSONObject o = (JSONObject)innerVal; 251 Iterator it = o.keys(); 252 while (it.hasNext()) 253 { 254 String k = (String)it.next(); 255 innerMap.put(k, o.get(k)); 256 } 257 innerVal = innerMap; 258 } 259 else if (innerVal instanceof Integer) 260 { 261 innerVal = ((Integer)innerVal).longValue(); 262 } 263 264 map.put(key, innerVal); 265 } 266 267 array[i] = map; 268 } 269 else 270 { 271 if (val == JSONObject.NULL) 272 { 273 array[i] = null; 274 } 275 else 276 { 277 array[i] = val; 278 } 279 } 280 } 281 282 return array; 283 } 284 285 private static void checkType(final Object param) 286 { 287 if (param instanceof Integer == false && param instanceof Long == false && 288 param instanceof Double == false && 289 param instanceof String == false && 290 param instanceof Boolean == false && 291 param instanceof Map == false && 292 param instanceof Byte == false && 293 param instanceof Short == false) 294 { 295 throw new IllegalArgumentException("Params for management operations must be of the following type: " + "int long double String boolean Map or array thereof " + 296 " but found " + 297 param.getClass().getName()); 298 } 299 } 300 301 /** 302 * Used by HornetQ management service. 303 */ 304 public static Object[] retrieveOperationParameters(final Message message) throws Exception 305 { 306 SimpleString sstring = message.getBodyBuffer().readNullableSimpleString(); 307 String jsonString = (sstring == null) ? null : sstring.toString(); 308 309 if (jsonString != null) 310 { 311 JSONArray jsonArray = new JSONArray(jsonString); 312 313 return ManagementHelper.fromJSONArray(jsonArray); 314 } 315 else 316 { 317 return null; 318 } 319 } 320 321 /** 322 * Returns whether the JMS message corresponds to the result of a management operation invocation. 323 */ 324 public static boolean isOperationResult(final Message message) 325 { 326 return message.containsProperty(ManagementHelper.HDR_OPERATION_SUCCEEDED); 327 } 328 329 /** 330 * Returns whether the JMS message corresponds to the result of a management attribute value. 331 */ 332 public static boolean isAttributesResult(final Message message) 333 { 334 return !ManagementHelper.isOperationResult(message); 335 } 336 337 /** 338 * Used by HornetQ management service. 339 */ 340 public static void storeResult(final Message message, final Object result) throws Exception 341 { 342 String resultString; 343 344 if (result != null) 345 { 346 // Result is stored in body, also encoded as JSON array of length 1 347 348 JSONArray jsonArray = ManagementHelper.toJSONArray(new Object[] { result }); 349 350 resultString = jsonArray.toString(); 351 } 352 else 353 { 354 resultString = null; 355 } 356 357 message.getBodyBuffer().writeNullableSimpleString(SimpleString.toSimpleString(resultString)); 358 } 359 360 /** 361 * Returns the result of an operation invocation or an attribute value. 362 * <br> 363 * If an error occurred on the server, {@link #hasOperationSucceeded(Message)} will return {@code false}. 364 * and the result will be a String corresponding to the server exception. 365 */ 366 public static Object[] getResults(final Message message) throws Exception 367 { 368 SimpleString sstring = message.getBodyBuffer().readNullableSimpleString(); 369 String jsonString = (sstring == null) ? null : sstring.toString(); 370 ; 371 if (jsonString != null) 372 { 373 JSONArray jsonArray = new JSONArray(jsonString); 374 375 Object[] res = ManagementHelper.fromJSONArray(jsonArray); 376 377 return res; 378 } 379 else 380 { 381 return null; 382 } 383 } 384 385 /** 386 * Returns the result of an operation invocation or an attribute value. 387 * <br> 388 * If an error occurred on the server, {@link #hasOperationSucceeded(Message)} will return {@code false}. 389 * and the result will be a String corresponding to the server exception. 390 */ 391 public static Object getResult(final Message message) throws Exception 392 { 393 Object[] res = ManagementHelper.getResults(message); 394 395 if (res != null) 396 { 397 return res[0]; 398 } 399 else 400 { 401 return null; 402 } 403 } 404 405 /** 406 * Returns whether the invocation of the management operation on the server resource succeeded. 407 */ 408 public static boolean hasOperationSucceeded(final Message message) 409 { 410 if (!ManagementHelper.isOperationResult(message)) 411 { 412 return false; 413 } 414 if (message.containsProperty(ManagementHelper.HDR_OPERATION_SUCCEEDED)) 415 { 416 return message.getBooleanProperty(ManagementHelper.HDR_OPERATION_SUCCEEDED); 417 } 418 return false; 419 } 420 421 /** 422 * Used by HornetQ management service. 423 */ 424 public static Map<String, Object> fromCommaSeparatedKeyValues(final String str) throws Exception 425 { 426 if (str == null || str.trim().length() == 0) 427 { 428 return Collections.emptyMap(); 429 } 430 431 // create a JSON array with 1 object: 432 JSONArray array = new JSONArray("[{" + str + "}]"); 433 Map<String, Object> params = (Map<String, Object>)ManagementHelper.fromJSONArray(array)[0]; 434 return params; 435 } 436 437 /** 438 * Used by HornetQ management service. 439 */ 440 public static Object[] fromCommaSeparatedArrayOfCommaSeparatedKeyValues(final String str) throws Exception 441 { 442 if (str == null || str.trim().length() == 0) 443 { 444 return new Object[0]; 445 } 446 447 String s = str; 448 449 // if there is a single item, we wrap it in to make it a JSON object 450 if (!s.trim().startsWith("{")) 451 { 452 s = "{" + s + "}"; 453 } 454 JSONArray array = new JSONArray("[" + s + "]"); 455 return ManagementHelper.fromJSONArray(array); 456 } 457 458 // Constructors -------------------------------------------------- 459 460 private ManagementHelper() 461 { 462 } 463 464 // Public -------------------------------------------------------- 465 466 // Package protected --------------------------------------------- 467 468 // Protected ----------------------------------------------------- 469 470 // Private ------------------------------------------------------- 471 472 // Inner classes ------------------------------------------------- 473}