    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
    014    package org.hornetq.api.core.management;
    015
    016    import java.util.Collections;
    017    import java.util.HashMap;
    018    import java.util.Iterator;
    019    import java.util.Map;
    020
    021    import org.hornetq.api.core.Message;
    022    import org.hornetq.api.core.SimpleString;
    023    import org.hornetq.core.logging.Logger;
    024    import org.hornetq.utils.json.JSONArray;
    025    import 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     */
    035    public 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    }