All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.flashlight.impl.client.FlashlightProbeClientMediator Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package org.glassfish.flashlight.impl.client;

/*
 * BOOBY TRAP SITTING RIGHT HERE!!! There is a ProbeListener in
 * org.glassfish.flashlight.client -- don't use that one or everything will
 * fail! Do not use this import --> import org.glassfish.flashlight.client.* -->
 * import individually instead!!
 */
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.util.reflect.ReflectUtils;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.glassfish.external.probe.provider.annotations.ProbeListener;
import org.glassfish.flashlight.FlashlightLoggerInfo;
import static org.glassfish.flashlight.FlashlightLoggerInfo.*;
import org.glassfish.flashlight.FlashlightUtils;
import org.glassfish.flashlight.client.ProbeClientInvoker;
import org.glassfish.flashlight.client.ProbeClientInvokerFactory;
import org.glassfish.flashlight.client.ProbeClientMediator;
import org.glassfish.flashlight.client.ProbeClientMethodHandle;
import org.glassfish.flashlight.impl.core.FlashlightProbeProvider;
import org.glassfish.flashlight.provider.FlashlightProbe;
import org.glassfish.flashlight.provider.ProbeRegistry;
import org.glassfish.hk2.api.PostConstruct;
import org.jvnet.hk2.annotations.Service;

/**
 * @author Mahesh Kannan Date: Jan 27, 2008
 * @author Byron Nevins, significant rewrite/refactor August 2009
 */
@Service
public class FlashlightProbeClientMediator
        implements ProbeClientMediator, PostConstruct {

    private static final ProbeRegistry probeRegistry = ProbeRegistry.getInstance();
    private static final Logger logger =
            FlashlightLoggerInfo.getLogger();
    public final static LocalStringManagerImpl localStrings =
            new LocalStringManagerImpl(FlashlightProbeClientMediator.class);
    private static FlashlightProbeClientMediator _me = new FlashlightProbeClientMediator();
    private AtomicInteger clientIdGenerator =
            new AtomicInteger(0);
    private static ConcurrentHashMap clients =
            new ConcurrentHashMap<>();

    @Override
    public void postConstruct() {
        FlashlightProbeClientMediator.initMe(this);
    }

    private static void initMe(FlashlightProbeClientMediator me) {
        _me = me;
    }

    public static FlashlightProbeClientMediator getInstance() {
        return _me;
    }

    public static Object getClient(int id) {
        return clients.get(id);
    }

    @Override
    public Collection registerListener(Object listener) {
        return (registerListener(listener, null));
    }

    @Override
    public Collection registerListener(Object listener, String invokerId) {

        List pcms = new ArrayList<>();
        List probesRequiringClassTransformation = new ArrayList<>();
        if (invokerId != null) {
            invokerId = FlashlightUtils.getUniqueInvokerId(invokerId);
        }
        registerJavaListener(listener, pcms, probesRequiringClassTransformation, invokerId);
        transformProbes(listener, probesRequiringClassTransformation);

        return pcms;
    }

    public Collection registerDTraceListener(FlashlightProbeProvider propro) {

        List pcms = new ArrayList<>();
        List probesRequiringClassTransformation = new ArrayList<>();

        Object listener = registerDTraceListener(propro, pcms, probesRequiringClassTransformation);
        transformProbes(listener, probesRequiringClassTransformation);

        return pcms;
    }

    private void registerJavaListener(
            Object listener,
            List pcms,
            List probesRequiringClassTransformation,
            String invokerId) {

        List methodProbePairs =
                handleListenerAnnotations(listener.getClass(), invokerId);

        if (methodProbePairs.isEmpty()) {
            return;
        }

        for (MethodProbe mp : methodProbePairs) {
            FlashlightProbe probe = mp.probe;
            ProbeClientInvoker invoker = ProbeClientInvokerFactory.createInvoker(listener, mp.method, probe);
            ProbeClientMethodHandleImpl hi = new ProbeClientMethodHandleImpl(invoker.getId(), invoker, probe);
            pcms.add(hi);

            if (probe.addInvoker(invoker))
                probesRequiringClassTransformation.add(probe);
        }
    }

    private Object registerDTraceListener(
            FlashlightProbeProvider propro,
            List pcms,
            List probesRequiringClassTransformation) {

        // The "listener" needs to be registered against every Probe in propro...

        Collection probes = propro.getProbes();
        Object listener = null;

        for (FlashlightProbe probe : probes) {
            ProbeClientInvoker invoker = ProbeClientInvokerFactory.createDTraceInvoker(probe);
            ProbeClientMethodHandleImpl hi = new ProbeClientMethodHandleImpl(invoker.getId(), invoker, probe);
            pcms.add(hi);

            if (probe.addInvoker(invoker))
                probesRequiringClassTransformation.add(probe);

            if (listener == null)
                listener = probe.getDTraceProviderImpl();    // all the probes in propro have the same "listener"
        }

        return listener;
    }

    @Override
    public void transformProbes(Object listener, List probes) {
        if (probes.isEmpty())
            return;

        int clientID = clientIdGenerator.incrementAndGet();
        clients.put(clientID, listener);

        for (FlashlightProbe probe : probes) {
            Class clz = probe.getProviderClazz();
            ProbeProviderClassFileTransformer transformer =
                    ProbeProviderClassFileTransformer.getInstance(clz);
            try {
                transformer.addProbe(probe);
            }
            catch (Exception ex) {
                logger.log(Level.SEVERE, BAD_TRANSFORM, ex);
            }
        }
    }

    /**
     * Pick out all methods in the listener with the correct annotation, look up
     * the referenced Probe and return a list of all such pairs. Validate that
     * the methods really do matchup properly.
     *
     * @throws RuntimeException if there is any serious problem.
     * @param listenerClass
     * @return
     */
    private List handleListenerAnnotations(Class listenerClass, String invokerId) {

        List mp = new LinkedList<>();

        for (Method method : listenerClass.getMethods()) {
            ProbeListener probeAnn = method.getAnnotation(ProbeListener.class);

            if (probeAnn == null)
                continue;

            String probeString = probeAnn.value();
            if (probeString == null)
                continue;

            if (invokerId != null) {
                String[] strArr = probeString.split(":");
                probeString = strArr[0] + ":"
                        + strArr[1] + ":"
                        + strArr[2] + invokerId + ":"
                        + strArr[3];
            }

            FlashlightProbe probe = probeRegistry.getProbe(probeString);
            if (probe == null) {
                String errStr = localStrings.getLocalString("probeNotRegistered",
                        "Probe is not registered: {0}", probeString);
                throw new RuntimeException(errStr);
            }
            mp.add(new MethodProbe(method, probe));
        }

        return mp;
    }

    // this is just used internally for cleanly organizing the code.
    // It throws RuntimeException because this module was specifically architected
    // to *not* use the Java Exception mechanism for errors.
    private static class MethodProbe {

        MethodProbe(Method m, FlashlightProbe p) {
            method = m;
            probe = p;
            String err = ReflectUtils.equalSignatures(method, p.getProbeMethod());

            if (err != null)
                throw new RuntimeException(Strings.get("method_mismatch", err));
        }
        Method method;
        FlashlightProbe probe;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy