001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.activemq.console.filter; 018 019 import java.lang.reflect.Method; 020 import java.util.Enumeration; 021 import java.util.HashMap; 022 import java.util.Iterator; 023 import java.util.Map; 024 import java.util.Properties; 025 import java.util.Arrays; 026 027 import javax.jms.DeliveryMode; 028 import javax.jms.JMSException; 029 import javax.management.Attribute; 030 import javax.management.AttributeList; 031 import javax.management.ObjectInstance; 032 import javax.management.ObjectName; 033 import javax.management.openmbean.CompositeDataSupport; 034 035 import org.apache.activemq.command.ActiveMQBytesMessage; 036 import org.apache.activemq.command.ActiveMQDestination; 037 import org.apache.activemq.command.ActiveMQMapMessage; 038 import org.apache.activemq.command.ActiveMQMessage; 039 import org.apache.activemq.command.ActiveMQObjectMessage; 040 import org.apache.activemq.command.ActiveMQStreamMessage; 041 import org.apache.activemq.command.ActiveMQTextMessage; 042 import org.apache.activemq.console.util.AmqMessagesUtil; 043 044 public class MapTransformFilter extends ResultTransformFilter { 045 /** 046 * Creates a Map transform filter that is able to transform a variety of 047 * objects to a properties map object 048 * 049 * @param next - the next query filter 050 */ 051 public MapTransformFilter(QueryFilter next) { 052 super(next); 053 } 054 055 /** 056 * Transform the given object to a Map object 057 * 058 * @param object - object to transform 059 * @return map object 060 */ 061 protected Object transformElement(Object object) throws Exception { 062 // Use reflection to determine how the object should be transformed 063 try { 064 Method method = this.getClass().getDeclaredMethod("transformToMap", new Class[] { 065 object.getClass() 066 }); 067 return (Map)method.invoke(this, new Object[] { 068 object 069 }); 070 } catch (NoSuchMethodException e) { 071 // CommandContext.print("Unable to transform mbean of type: " + object.getClass().getName() + ". No corresponding transformToMap method found."); 072 return null; 073 } 074 } 075 076 /** 077 * Transform an ObjectInstance mbean to a Map 078 * 079 * @param obj - ObjectInstance format of an mbean 080 * @return map object 081 */ 082 protected Map transformToMap(ObjectInstance obj) { 083 return transformToMap(obj.getObjectName()); 084 } 085 086 /** 087 * Transform an ObjectName mbean to a Map 088 * 089 * @param objname - ObjectName format of an mbean 090 * @return map object 091 */ 092 protected Map transformToMap(ObjectName objname) { 093 Properties props = new Properties(); 094 095 // Parse object properties 096 Map objProps = objname.getKeyPropertyList(); 097 for (Iterator i = objProps.keySet().iterator(); i.hasNext();) { 098 Object key = i.next(); 099 Object val = objProps.get(key); 100 if (val != null) { 101 props.setProperty(key.toString(), getDisplayString(val)); 102 } 103 } 104 105 return props; 106 } 107 108 /** 109 * Transform an Attribute List format of an mbean to a Map 110 * 111 * @param list - AttributeList format of an mbean 112 * @return map object 113 */ 114 protected Map transformToMap(AttributeList list) { 115 Properties props = new Properties(); 116 for (Iterator i = list.iterator(); i.hasNext();) { 117 Attribute attrib = (Attribute)i.next(); 118 119 // If attribute is an ObjectName 120 if (attrib.getName().equals(MBeansAttributeQueryFilter.KEY_OBJECT_NAME_ATTRIBUTE)) { 121 props.putAll(transformToMap((ObjectName)attrib.getValue())); 122 } else { 123 if (attrib.getValue() != null) { 124 props.setProperty(attrib.getName(), getDisplayString(attrib.getValue())); 125 } 126 } 127 } 128 129 return props; 130 } 131 132 /** 133 * Transform an ActiveMQTextMessage to a Map 134 * 135 * @param msg - text message to trasnform 136 * @return map object 137 * @throws JMSException 138 */ 139 protected Map transformToMap(ActiveMQTextMessage msg) throws JMSException { 140 Properties props = new Properties(); 141 142 props.putAll(transformToMap((ActiveMQMessage)msg)); 143 if (msg.getText() != null) { 144 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + "JMSText", msg.getText()); 145 } 146 147 return props; 148 } 149 150 /** 151 * Transform an ActiveMQBytesMessage to a Map 152 * 153 * @param msg - bytes message to transform 154 * @return map object 155 * @throws JMSException 156 */ 157 protected Map transformToMap(ActiveMQBytesMessage msg) throws JMSException { 158 Properties props = new Properties(); 159 160 props.putAll(transformToMap((ActiveMQMessage)msg)); 161 162 long bodyLength = msg.getBodyLength(); 163 byte[] msgBody; 164 int i = 0; 165 // Create separate bytes messages 166 for (i = 0; i < (bodyLength / Integer.MAX_VALUE); i++) { 167 msgBody = new byte[Integer.MAX_VALUE]; 168 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + "JMSBytes:" + (i + 1), new String(msgBody)); 169 } 170 msgBody = new byte[(int)(bodyLength % Integer.MAX_VALUE)]; 171 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + "JMSBytes:" + (i + 1), new String(msgBody)); 172 173 return props; 174 } 175 176 /** 177 * Transform an ActiveMQMessage to a Map 178 * 179 * @param msg - object message to transform 180 * @return map object 181 * @throws JMSException 182 */ 183 protected Map transformToMap(ActiveMQObjectMessage msg) throws JMSException { 184 Properties props = new Properties(); 185 186 props.putAll(transformToMap((ActiveMQMessage)msg)); 187 if (msg.getObject() != null) { 188 // Just add the class name and toString value of the object 189 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + "JMSObjectClass", msg.getObject().getClass().getName()); 190 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + "JMSObjectString", getDisplayString(msg.getObject())); 191 } 192 return props; 193 } 194 195 /** 196 * Transform an ActiveMQMapMessage to a Map 197 * 198 * @param msg - map message to transform 199 * @return map object 200 * @throws JMSException 201 */ 202 protected Map transformToMap(ActiveMQMapMessage msg) throws JMSException { 203 Properties props = new Properties(); 204 205 props.putAll(transformToMap((ActiveMQMessage)msg)); 206 207 // Get map properties 208 Enumeration e = msg.getMapNames(); 209 while (e.hasMoreElements()) { 210 String key = (String)e.nextElement(); 211 Object val = msg.getObject(key); 212 if (val != null) { 213 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + key, getDisplayString(val)); 214 } 215 } 216 217 return props; 218 } 219 220 /** 221 * Transform an ActiveMQStreamMessage to a Map 222 * 223 * @param msg - stream message to transform 224 * @return map object 225 * @throws JMSException 226 */ 227 protected Map transformToMap(ActiveMQStreamMessage msg) throws JMSException { 228 Properties props = new Properties(); 229 230 props.putAll(transformToMap((ActiveMQMessage)msg)); 231 // Just set the toString of the message as the body of the stream 232 // message 233 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + "JMSStreamMessage", getDisplayString(msg)); 234 235 return props; 236 } 237 238 /** 239 * Transform an ActiveMQMessage to a Map 240 * 241 * @param msg - message to transform 242 * @return map object 243 * @throws JMSException 244 */ 245 protected Map<String, String> transformToMap(ActiveMQMessage msg) throws JMSException { 246 Map<String, String> props = new HashMap<String, String>(); 247 248 // Get JMS properties 249 if (msg.getJMSCorrelationID() != null) { 250 props.put(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSCorrelationID", msg.getJMSCorrelationID()); 251 } 252 props.put(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSDeliveryMode", (msg.getJMSDeliveryMode() == DeliveryMode.PERSISTENT) ? "persistent" : "non-persistent"); 253 if (msg.getJMSDestination() != null) { 254 props.put(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSDestination", ((ActiveMQDestination)msg.getJMSDestination()).getPhysicalName()); 255 } 256 props.put(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSExpiration", Long.toString(msg.getJMSExpiration())); 257 props.put(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSMessageID", msg.getJMSMessageID()); 258 props.put(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSPriority", Integer.toString(msg.getJMSPriority())); 259 props.put(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSRedelivered", Boolean.toString(msg.getJMSRedelivered())); 260 if (msg.getJMSReplyTo() != null) { 261 props.put(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSReplyTo", ((ActiveMQDestination)msg.getJMSReplyTo()).getPhysicalName()); 262 } 263 props.put(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSTimestamp", Long.toString(msg.getJMSTimestamp())); 264 if (msg.getJMSType() != null) { 265 props.put(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSType", msg.getJMSType()); 266 } 267 268 // Get custom properties 269 Enumeration e = msg.getPropertyNames(); 270 while (e.hasMoreElements()) { 271 String name = (String)e.nextElement(); 272 if (msg.getObjectProperty(name) != null) { 273 props.put(AmqMessagesUtil.JMS_MESSAGE_CUSTOM_PREFIX + name, getDisplayString(msg.getObjectProperty(name))); 274 } 275 } 276 277 return props; 278 } 279 280 /** 281 * Transform an openMBean composite data to a Map 282 * 283 * @param data - composite data to transform 284 * @return map object 285 */ 286 protected Map transformToMap(CompositeDataSupport data) { 287 Properties props = new Properties(); 288 289 String typeName = data.getCompositeType().getTypeName(); 290 291 // Retrieve text message 292 if (typeName.equals(ActiveMQTextMessage.class.getName())) { 293 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + "Text", data.get("Text").toString()); 294 295 // Retrieve byte preview 296 } else if (typeName.equals(ActiveMQBytesMessage.class.getName())) { 297 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + "BodyLength", data.get("BodyLength").toString()); 298 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + "BodyPreview", new String((byte[])data.get("BodyPreview"))); 299 300 // Expand content map 301 } else if (typeName.equals(ActiveMQMapMessage.class.getName())) { 302 Map contentMap = (Map)data.get("ContentMap"); 303 for (Iterator i = contentMap.keySet().iterator(); i.hasNext();) { 304 String key = (String)i.next(); 305 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_BODY_PREFIX + key, contentMap.get(key).toString()); 306 } 307 308 // Do nothing 309 } else if (typeName.equals(ActiveMQObjectMessage.class.getName()) || typeName.equals(ActiveMQStreamMessage.class.getName()) || typeName.equals(ActiveMQMessage.class.getName())) { 310 311 // Unrecognized composite data. Throw exception. 312 } else { 313 throw new IllegalArgumentException("Unrecognized composite data to transform. composite type: " + typeName); 314 } 315 316 // Process the JMS message header values 317 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSCorrelationID", "" + data.get("JMSCorrelationID")); 318 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSDestination", "" + data.get("JMSDestination")); 319 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSMessageID", "" + data.get("JMSMessageID")); 320 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSReplyTo", "" + data.get("JMSReplyTo")); 321 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSType", "" + data.get("JMSType")); 322 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSDeliveryMode", "" + data.get("JMSDeliveryMode")); 323 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSExpiration", "" + data.get("JMSExpiration")); 324 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSPriority", "" + data.get("JMSPriority")); 325 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSRedelivered", "" + data.get("JMSRedelivered")); 326 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_HEADER_PREFIX + "JMSTimestamp", "" + data.get("JMSTimestamp")); 327 328 // Process the JMS custom message properties 329 props.setProperty(AmqMessagesUtil.JMS_MESSAGE_CUSTOM_PREFIX + "Properties", "" + data.get("Properties")); 330 331 return props; 332 } 333 334 protected String getDisplayString(Object obj) { 335 if (obj != null && obj.getClass().isArray()) { 336 obj = Arrays.asList((Object[]) obj); 337 } 338 return obj.toString(); 339 } 340 }