Package com.springsource.insight.plugin.rabbitmqClient

Source Code of com.springsource.insight.plugin.rabbitmqClient.AbstractRabbitMQCollectionAspect

/**
* Copyright (c) 2009-2011 VMware, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.springsource.insight.plugin.rabbitmqClient;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;

import org.aspectj.lang.JoinPoint;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.impl.AMQConnection;
import com.springsource.insight.collection.OperationCollectionAspectSupport;
import com.springsource.insight.collection.OperationCollectionUtil;
import com.springsource.insight.intercept.color.ColorManager.ColorParams;
import com.springsource.insight.intercept.operation.Operation;
import com.springsource.insight.intercept.operation.OperationMap;
import com.springsource.insight.util.ArrayUtil;
import com.springsource.insight.util.ClassUtil;
import com.springsource.insight.util.ExtraReflectionUtils;
import com.springsource.insight.util.MapUtil;
import com.springsource.insight.util.ReflectionUtils;
import com.springsource.insight.util.logging.InsightLogManager;

public abstract class AbstractRabbitMQCollectionAspect extends OperationCollectionAspectSupport {
    private static final AtomicReference<Field> messageHeadersField = new AtomicReference<Field>(null);
    private static final AtomicReference<Class<?>> longStringClassHolder = new AtomicReference<Class<?>>(null);
    private static final AtomicReference<Object> bytesMethodHolder = new AtomicReference<Object>(null);

    static final List<String> LONG_STRING_CLASSES =
            Collections.unmodifiableList(
                    Arrays.asList(
                            "com.rabbitmq.client.impl.LongString",
                            "com.rabbitmq.client.LongString"));

    protected final RabbitPluginOperationType pluginOpType;

    protected AbstractRabbitMQCollectionAspect(RabbitPluginOperationType rabbitOpType) {
        if ((pluginOpType = rabbitOpType) == null) {
            throw new IllegalStateException("No plugin operation type specified");
        }
    }

    @Override
    public String getPluginName() {
        return RabbitMQPluginRuntimeDescriptor.PLUGIN_NAME;
    }

    protected Operation createOperation(JoinPoint jp) {
        return new Operation()
                .type(pluginOpType.getOperationType())
                .label(pluginOpType.getLabel())
                .sourceCodeLocation(OperationCollectionUtil.getSourceCodeLocation(jp))
                ;
    }

    protected void applyPropertiesData(Operation op, BasicProperties props) {
        OperationMap map = op.createMap("props");

        map.putAnyNonEmpty("Type", props.getType());
        map.putAnyNonEmpty("App Id", props.getAppId());
        map.putAnyNonEmpty("User Id", props.getUserId());
        map.put("Class Id", props.getClassId());
        map.putAnyNonEmpty("Reply To", props.getReplyTo());
        map.putAnyNonEmpty("Priority", props.getPriority());
        map.putAnyNonEmpty("Class Name", props.getClassName());
        map.putAnyNonEmpty("Timestamp", props.getTimestamp());
        map.putAnyNonEmpty("Message Id", props.getMessageId());
        map.putAnyNonEmpty("Expiration", props.getExpiration());
        map.putAnyNonEmpty("Content Type", props.getContentType());
        map.putAnyNonEmpty("Delivery Mode", props.getDeliveryMode());
        map.putAnyNonEmpty("Correlation Id", props.getCorrelationId());
        map.putAnyNonEmpty("Content Encoding", props.getContentEncoding());

        updateHeadersMap(op, props.getHeaders());
    }

    protected OperationMap updateHeadersMap(Operation op, Map<String, ?> headers) {
        return updateHeadersMap(op.createMap("headers"), headers);
    }

    protected OperationMap updateHeadersMap(OperationMap headersMap, Map<String, ?> headers) {
        if (MapUtil.size(headers) <= 0) {
            return headersMap;
        }

        Class<?> longStringClass = getLongStringClass(getClass());
        if (longStringClass == null) {
            return headersMap;
        }

        Method bytesMethod = getBytesRetrievalMethod(getClass());
        if (bytesMethod == null) {
            return headersMap;
        }

        for (Map.Entry<String, ?> entry : headers.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value == null) {
                continue;
            }

            Class<?> valueType = value.getClass();
            if (!valueType.isAssignableFrom(longStringClass)) {
                continue;
            }

            final byte[] bytes;
            try {
                bytes = (byte[]) bytesMethod.invoke(value);
                if (ArrayUtil.length(bytes) <= 0) {
                    continue;
                }
            } catch (Exception e) {
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.fine("Failed (" + e.getClass().getSimpleName() + ")"
                            + " to get bytes of " + valueType.getName()
                            + " instance for key=" + key + ": " + e.getMessage());
                }
                continue;
            }

            headersMap.put(key, new String(bytes));
        }

        return headersMap;
    }

    protected void applyConnectionData(Operation op, Connection conn) {
        InetAddress address = conn.getAddress();
        String host = address.getHostAddress();
        int port = conn.getPort();
        final String connectionUrl;
        if (conn instanceof AMQConnection) {
            connectionUrl = conn.toString();
        } else {
            connectionUrl = "amqp://" + host + ":" + port;
        }

        op.put("host", host);
        op.put("port", port);
        op.put("connectionUrl", connectionUrl);

        //try to extract server version
        String serverVersion = getVersion(conn.getServerProperties());
        op.putAnyNonEmpty("serverVersion", serverVersion);

        //try to extract client version
        String clientVersion = getVersion(conn.getClientProperties());
        op.putAnyNonEmpty("clientVersion", clientVersion);
    }

    static String getVersion(Map<String, ?> properties) {
        if (MapUtil.size(properties) <= 0) {
            return null;
        }

        Object obj = properties.get("version");
        if (obj != null) {
            return String.valueOf(obj);
        } else {
            return null;
        }
    }

    protected BasicProperties colorForward(BasicProperties orgProps, final Operation op) {
        Field headersField = getMessageHeadersField();
        BasicProperties props = orgProps;
        if (headersField == null) {
            return props;
        }

        try {
            final Map<String, Object> map = new HashMap<String, Object>();
            Map<String, Object> old = (props != null) ? props.getHeaders() : null;
            if (MapUtil.size(old) > 0) {
                map.putAll(old);
            }

            colorForward(new ColorParams() {
                public void setColor(String key, String value) {
                    map.put(key, value);
                }

                public Operation getOperation() {
                    return op;
                }
            });

            if (props == null) {
                BasicProperties.Builder builder = new BasicProperties.Builder();
                props = builder.build();
            }

            Map<String, Object> hdrsMap = Collections.unmodifiableMap(map);
            ReflectionUtils.setField(headersField, props, hdrsMap);
            return props;
        } catch (Exception e) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("colorForward(" + op + ")"
                        + " failed (" + e.getClass().getSimpleName() + ")"
                        + " to append color: " + e.getMessage());
            }

            return props;
        }
    }

    static Field getMessageHeadersField() {
        // kind of a D.C.L. but works...
        Field field = messageHeadersField.get();
        if (field == null) {
            if ((field = ExtraReflectionUtils.getAccessibleField(BasicProperties.class, "headers")) != null) {
                messageHeadersField.set(field);
            }
        }

        return field;
    }

    static Method getBytesRetrievalMethod(Class<?> anchor) {
        Object method = bytesMethodHolder.get();
        if (method != null) {
            if (method instanceof Boolean) {
                return null;
            } else {
                return (Method) method;
            }
        }

        Class<?> longStringClass = getLongStringClass(anchor);
        if (longStringClass == null) {
            return null;
        }

        if ((method = ExtraReflectionUtils.getAccessibleMethod(longStringClass, "getBytes")) == null) {
            InsightLogManager.getLogger(anchor.getName())
                    .warning("getBytesRetrievalMethod(" + anchor.getSimpleName() + ") no match found")
            ;
            bytesMethodHolder.set(Boolean.FALSE);    // avoid repeated calls
            return null;
        }

        bytesMethodHolder.set(method);
        return (Method) method;
    }

    static Class<?> getLongStringClass(Class<?> anchor) {
        Class<?> clazz = longStringClassHolder.get();
        if (clazz != null) {
            // check if placeholder used
            if (clazz == String.class) {
                return null;
            } else {
                return clazz;
            }
        }

        ClassLoader cl = ClassUtil.getDefaultClassLoader(anchor);
        for (String className : LONG_STRING_CLASSES) {
            try {
                if ((clazz = ClassUtil.loadClassByName(cl, className)) == null) {
                    throw new IllegalStateException("Failed to load present class");
                }

                longStringClassHolder.set(clazz);
                return clazz;
            } catch (Exception e) {
                if (!(e instanceof ClassNotFoundException)) {
                    InsightLogManager.getLogger(anchor.getName())
                            .warning("Failed (" + e.getClass().getSimpleName() + ")"
                                    + " to load class=" + className
                                    + ": " + e.getMessage());
                }
            }
        }

        InsightLogManager.getLogger(anchor.getName())
                .warning("getLongStringClass(" + anchor.getSimpleName() + ") no match found");
        longStringClassHolder.set(String.class);    // avoid repeated load attempts and use an incompatible class
        return null;
    }

    @Override
    public boolean isMetricsGenerator() {
        return true; // This provides an endpoint and external resource
    }
}
TOP

Related Classes of com.springsource.insight.plugin.rabbitmqClient.AbstractRabbitMQCollectionAspect

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.