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