Package org.apache.sirona.javaagent

Source Code of org.apache.sirona.javaagent.AgentContext$ListenerComparator

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.sirona.javaagent;

import org.apache.sirona.Role;
import org.apache.sirona.configuration.ioc.IoCs;
import org.apache.sirona.counters.Counter;
import org.apache.sirona.javaagent.spi.InvocationListener;
import org.apache.sirona.javaagent.spi.InvocationListenerFactory;
import org.apache.sirona.spi.Order;
import org.apache.sirona.spi.SPI;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

// just a helper to ease ASM work and reuse AbstractPerformanceInterceptor logic
public class AgentContext {

    private static final InvocationListener[] EXISTING_LISTENERS = loadAllListeners();

    private static final ConcurrentMap<String, InvocationListener[]> LISTENERS_BY_KEY = new ConcurrentHashMap<String, InvocationListener[]>();
    private static final ConcurrentMap<String, Counter.Key> KEYS_CACHE = new ConcurrentHashMap<String, Counter.Key>();
  private static final AgentContext FAKE_CONTEXT = new AgentContext("init", null, new InvocationListener[0]);

  private static final Map<String, String> AGENT_PARAMETERS = new ConcurrentHashMap<String, String>();

    public static void addAgentParameter( String key, String value){
        AGENT_PARAMETERS.put(key, value);
    }

    /**
     *
     * @return a copy of the Agent parameters
     */
    public static Map<String,String> getAgentParameters(){
        return AGENT_PARAMETERS;
    }

    // called by agent
    public static AgentContext startOn(final Object that, final String key) {
    if (key == null) { // possible in static inits, the best would be to ignore it in instrumentation
      return FAKE_CONTEXT;
    }
        return new AgentContext(key, that, listeners(key));
    }

    // helper to init keys in javaagent
    public static Counter.Key key(final String name) {
        Counter.Key key = KEYS_CACHE.get(name);
        if (key == null) {
            key = new Counter.Key(Role.PERFORMANCES, name);
            KEYS_CACHE.putIfAbsent(name, key);
        }
        return key;
    }

    private static InvocationListener[] loadAllListeners() {
        final Collection<InvocationListener> listeners = new LinkedList<InvocationListener>();

        ClassLoader agentLoader = AgentContext.class.getClassLoader();
        if (agentLoader == null) {
            agentLoader = ClassLoader.getSystemClassLoader();
        }

        for (final InvocationListener listener : SPI.INSTANCE.find(InvocationListener.class, agentLoader)) {
            addListener(listeners, null, listener);
        }
        for (final InvocationListenerFactory factory : SPI.INSTANCE.find(InvocationListenerFactory.class, agentLoader)) {
            final Map<String, InvocationListener> listenerMap = factory.listeners();
            if (listenerMap != null) {
                for (final Map.Entry<String, InvocationListener> listener : listenerMap.entrySet()) {
                    addListener(listeners, listener.getKey(), listener.getValue());
                }
            }
        }
        //System.out.println("listeners:" + listeners.toString());
        return listeners.toArray(new InvocationListener[listeners.size()]);
    }

    private static void addListener(final Collection<InvocationListener> listeners, final String key, final InvocationListener listener) {
        InvocationListener autoset;
        try {
            autoset = IoCs.autoSet(key, listener);
        } catch (final Exception e) {
            autoset = listener;
        }
        listeners.add(autoset);
    }

    public static InvocationListener[] listeners(final String key) {
        InvocationListener[] listeners = LISTENERS_BY_KEY.get(key);
        if (listeners == null) {
            listeners = findListeners(key);
            if (listeners.length == 0) {
                return null;
            }

            final InvocationListener[] old = LISTENERS_BY_KEY.putIfAbsent(key, listeners);
      if (old != null) {
        listeners = old;
            }
        }
        return listeners;
    }

    private static InvocationListener[] findListeners(final String key) {
        final List<InvocationListener> listeners = new LinkedList<InvocationListener>();
        for (final InvocationListener listener : EXISTING_LISTENERS) {
            if (listener.accept(key)) {
                listeners.add(listener);
            }
        }
        Collections.sort( listeners, ListenerComparator.INSTANCE );
        return listeners.toArray(new InvocationListener[listeners.size()]);
    }

    private final String key;
    private final Object reference;
    private final InvocationListener[] listeners;
    private final Map<Integer, Object> context = new HashMap<Integer, Object>();
    private Method method = null;

    public AgentContext(final String key, final Object that, final InvocationListener[] listeners) {
        this.key = key;
        this.reference = that;
        this.listeners = listeners;
        for (final InvocationListener listener : this.listeners) {
            listener.before(this);
        }
    }

    public Object getReference() {
        return reference;
    }

    public String getKey() {
        return key;
    }

    public Class<?> keyAsClass() {
        try {
            Method method = keyAsMethod();
            return method == null ? null : method.getDeclaringClass();
        } catch (final Throwable th) {
            return null;
        }
    }

    public Method keyAsMethod() {
        if (method != null) {
            return method;
        }

        final int lastDot = key.lastIndexOf('.');
        try {
            method = tccl().loadClass(key.substring(0, lastDot)).getDeclaredMethod(key.substring(lastDot + 1));
        } catch (final Throwable th) {
            return null;
        }
        return method;
    }

    private static ClassLoader tccl() {
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        if (contextClassLoader == null) {
            contextClassLoader = ClassLoader.getSystemClassLoader();
        }
        return contextClassLoader;
    }

    public <T> T get(final Integer key, final Class<T> clazz) {
        return clazz.cast(context.get(key));
    }

    public void put(final int key, Object data) {
        context.put(key, data);
    }

    public void stop(final Object result) {
        stopListeners(result, null);
    }

    public void stopWithException(final Throwable error) {
        stopListeners(null, error);
    }

    private void stopListeners(final Object result, final Throwable error) {
        for (final InvocationListener listener : listeners) {
            listener.after(this, result, error);
        }
    }

    private static class ListenerComparator implements Comparator<InvocationListener>
    {
        private static final ListenerComparator INSTANCE = new ListenerComparator();

        private ListenerComparator() {
            // no-op
        }

        @Override
        public int compare(final InvocationListener o1, final InvocationListener o2) {
            final Order order1 = o1.getClass().getAnnotation(Order.class);
            final Order order2 = o2.getClass().getAnnotation(Order.class);
            if (order2 == null) {
                return -1;
            }
            if (order1 == null) {
                return 1;
            }
            return order1.value() - order2.value();
        }
    }
}
TOP

Related Classes of org.apache.sirona.javaagent.AgentContext$ListenerComparator

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.