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

org.glassfish.flashlight.impl.provider.FlashlightProbeProviderFactory Maven / Gradle / Ivy

There is a newer version: 4.1.2.181
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.provider;

import org.glassfish.external.probe.provider.annotations.*;
import org.glassfish.flashlight.xml.ProbeProviderStaxParser;
import com.sun.enterprise.config.serverbeans.MonitoringService;
import com.sun.enterprise.util.ObjectAnalyzer;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
import org.glassfish.api.monitoring.DTraceContract;
import org.glassfish.flashlight.FlashlightLoggerInfo;
import static org.glassfish.flashlight.FlashlightLoggerInfo.*;
import org.glassfish.flashlight.FlashlightUtils;
import org.glassfish.flashlight.impl.client.FlashlightProbeClientMediator;
import org.glassfish.flashlight.provider.*;
import org.glassfish.flashlight.impl.core.*;
import org.glassfish.flashlight.provider.ProbeProviderFactory;
import org.jvnet.hk2.annotations.Service;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.text.MessageFormat;

import org.glassfish.hk2.api.PostConstruct;
import org.glassfish.hk2.api.ServiceLocator;

import javax.inject.Inject;

/**
 * @author Mahesh Kannan
 * @author Byron Nevins
 * @author Prashanth Abbagani
 */
@Service
public class FlashlightProbeProviderFactory
        implements ProbeProviderFactory, PostConstruct {
    @Inject
    //Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
    MonitoringService monitoringServiceConfig;

    @Inject
    ProbeProviderEventManager ppem;

    @Inject
    ServiceLocator habitat;

    private List listeners = new ArrayList();

    private final static Set allProbeProviders = new HashSet();
    private static final Logger logger = FlashlightLoggerInfo.getLogger();
    private static final ResourceBundle rb = logger.getResourceBundle();

    private static final HashMap primTypes = new HashMap() {
        {
            put("int",Integer.TYPE);
            put("byte",Byte.TYPE);
            put("char",Character.TYPE);
            put("short",Short.TYPE);
            put("long",Long.TYPE);
            put("float",Float.TYPE);
            put("double",Double.TYPE);
            put("boolean",Boolean.TYPE);
            put("void",Void.TYPE);
        }
    };

    public void postConstruct() {
        FlashlightUtils.initialize(habitat, monitoringServiceConfig);
    }

    public void dtraceEnabledChanged(boolean newValue) {
        FlashlightUtils.setDTraceEnabled(newValue);

        // if true->false we just need to set the enabled flag
        // DTrace invoker will simply not call the already-built
        // DTrace objects

        if(newValue == false)
            return;

        // if it still is not available -- return.  E.g. they set the flag
        // but they don't have the native libs

        if(!FlashlightUtils.isDtraceAvailable())
            return;

        // if false-> true we might need to create all the DTrace classes.  It
        // depends on whether the server started up with it true, etc.
        // loop through all the Providers -- if any don't have DTrace then
        // instrument with DTrace
        Collection pps = ProbeProviderRegistry.getInstance().getAllProbeProviders();

        for(FlashlightProbeProvider pp : pps) {
            if(!pp.isDTraceInstrumented()) {
                handleDTrace(pp);
            }
        }
    }

    public void monitoringEnabledChanged(boolean newValue) {
        FlashlightUtils.setMonitoringEnabled(newValue);

        // if monitoring-enabled is going false -> true AND
        // dtrace-enabled is true -- then we need to do something
        // o/w we don't have to do anything

        if(newValue == true && FlashlightUtils.isDtraceEnabled())
            dtraceEnabledChanged(true);
    }

    public  T getProbeProvider(Class providerClazz)
            throws InstantiationException, IllegalAccessException {
        return getProbeProvider(providerClazz, null);
    }

    public  T getProbeProvider(Class providerClazz, String invokerId)
            throws InstantiationException, IllegalAccessException {

        if (providerClazz == null) {
            throw new NullPointerException("providerClazz cannot be null");
        }

        ProbeProvider provAnn = providerClazz.getAnnotation(ProbeProvider.class);

        String moduleProviderName = null;
        String moduleName = null;
        String probeProviderName = null;

        if (provAnn != null) {
            moduleProviderName = provAnn.moduleProviderName();
            moduleName = provAnn.moduleName();
            probeProviderName = provAnn.probeProviderName();
        }

        if (moduleProviderName == null) {
            moduleProviderName = providerClazz.getName();
        }

        if (moduleName == null) {
            moduleName = providerClazz.getName();
        }

        if (probeProviderName == null) {
            probeProviderName = providerClazz.getSimpleName();
        }

        if (isValidString(moduleProviderName)
                && isValidString(moduleName)
                && isValidString(probeProviderName)) {
            return getProbeProvider(moduleProviderName, moduleName,
                    probeProviderName,
                    invokerId, providerClazz);
        } else {
            logger.log(Level.WARNING,
                    INVALID_PROBE_PROVIDER, new Object[]{providerClazz.getName()});
            return null;
        }
    }

    public  T getProbeProvider(String moduleName, String providerName, String appName,
                                  Class clazz)
            throws InstantiationException, IllegalAccessException {

        return getProbeProvider(moduleName, providerName, appName, null, clazz);
    }

    public  T getProbeProvider(String moduleProviderName, String moduleName,
    		String probeProviderName, String invokerId,
    		Class providerClazz)
            throws InstantiationException, IllegalAccessException {

        String origProbeProviderName = probeProviderName;
        Class oldProviderClazz = providerClazz;

        ProbeProviderRegistry ppRegistry = ProbeProviderRegistry.getInstance();
        FlashlightProbeProvider genericProvider = null;
        if (invokerId != null) {
            getProbeProvider( moduleProviderName,  moduleName,
    		 probeProviderName, null, providerClazz);
            genericProvider = new FlashlightProbeProvider(
                moduleProviderName, moduleName, probeProviderName, providerClazz);
            genericProvider = ppRegistry.getProbeProvider(genericProvider);

            invokerId = FlashlightUtils.getUniqueInvokerId(invokerId);
            probeProviderName += invokerId;
            try {
                providerClazz = getGeneratedProbeProviderClass(oldProviderClazz, invokerId);

            } catch (Exception ex) {
                //TODO
                providerClazz = oldProviderClazz;
            }
        }
        FlashlightProbeProvider provider = new FlashlightProbeProvider(
                moduleProviderName, moduleName, probeProviderName, providerClazz);
        if (logger.isLoggable(Level.FINE)) {
            logger.fine("ModuleProviderName= " + moduleProviderName + " \tModule= " + moduleName
                + "\tProbeProviderName= " + probeProviderName + "\tProviderClazz= " + providerClazz.toString());
        }

        // IT 10269 -- silently return a fresh instance if it is already registered
        // don't waste time -- return right away...

        FlashlightProbeProvider alreadyExists = ppRegistry.getProbeProvider(provider);

        if(alreadyExists != null) {
            T inst = (T) alreadyExists.getProviderClass().newInstance();
            notifyListenersOnAdd(moduleProviderName, moduleName,
                    probeProviderName, invokerId, providerClazz, inst);
            return inst;
        }

        List methods = FlashlightUtils.getProbeMethods(providerClazz);

        // If none of the method are annotated with @Probe, then register all
        // public methods as probe providers
        boolean isProbeAnnotationPresent = false;

        for (Method m : methods) {
            Probe pnameAnn = m.getAnnotation(Probe.class);
            boolean self = false;
            boolean hidden = false;
            String probeName = m.getName();
            if (pnameAnn != null) {
                isProbeAnnotationPresent = true;
                self = pnameAnn.self();
                hidden = pnameAnn.hidden();
                if (pnameAnn.name() != null && !pnameAnn.name().isEmpty()) {
                    probeName = pnameAnn.name();
                }

                createProbe(origProbeProviderName, genericProvider, provider,
                        probeName, self, hidden, m, moduleProviderName, moduleName, probeProviderName,
                        invokerId, providerClazz, pnameAnn.stateful(), pnameAnn.statefulReturn(),
                        pnameAnn.statefulException(), pnameAnn.profileNames());

            }
        }

        if (!isProbeAnnotationPresent) {  //Let's do all public methods
            for (Method m : providerClazz.getDeclaredMethods()) {
                String methodName = m.getName();

                createProbe(origProbeProviderName, genericProvider, provider,
                        methodName, false, false, m, moduleProviderName, moduleName, probeProviderName,
                        invokerId, providerClazz,
                        false, false, false, null); // Not stateful and no profile names for these
            }
        }

        handleDTrace(provider);

        Class tClazz = providerClazz;

        int mod = providerClazz.getModifiers();
        if (Modifier.isAbstract(mod)) {

            String generatedClassName = provider.getModuleProviderName() +
                    "_Flashlight_" + provider.getModuleName() + "_" + "Probe_" +
                    ((provider.getProbeProviderName() == null) ? providerClazz.getName() : provider.getProbeProviderName());
            generatedClassName = providerClazz.getName() + "_" + generatedClassName;

            try {
                tClazz = (Class) (providerClazz.getClassLoader()).loadClass(generatedClassName);
                //System.out.println ("Reusing the Generated class");
                T inst = (T) tClazz.newInstance();
                notifyListenersOnAdd(moduleProviderName, moduleName,
                        probeProviderName, invokerId, providerClazz, inst);
                return inst;
            } catch (ClassNotFoundException cnfEx) {
                //Ignore
            }

            ProviderImplGenerator gen = new ProviderImplGenerator();
            generatedClassName = gen.defineClass(provider, providerClazz);

            try {
                tClazz = (Class) providerClazz.getClassLoader().loadClass(generatedClassName);
            } catch (ClassNotFoundException cnfEx) {
                throw new RuntimeException(cnfEx);
            }
        }

        ppRegistry.getInstance().registerProbeProvider(
                provider, tClazz);

        T inst = (T) tClazz.newInstance();
        notifyListenersOnAdd(moduleProviderName, moduleName,
                probeProviderName, invokerId, providerClazz, inst);
        return inst;
    }

    private void createProbe(String origProbeProviderName, FlashlightProbeProvider genericProvider,
            FlashlightProbeProvider provider, String probeName, boolean self, boolean hidden,
            Method m, String moduleProviderName, String moduleName,
    		String probeProviderName, String invokerId,
    		Class providerClazz, boolean stateful, boolean statefulReturn,
    		boolean statefulException, String profileNames) {

            String[] probeParamNames = FlashlightUtils.getParamNames(m);
            FlashlightProbe probe = ProbeFactory.createProbe(
                    providerClazz, moduleProviderName, moduleName, probeProviderName, probeName,
                    probeParamNames, m.getParameterTypes(), self, hidden,
                    stateful, statefulReturn, statefulException, splitProfileNames(profileNames));
            probe.setProviderJavaMethodName(m.getName());
            probe.setProbeMethod(m);
            provider.addProbe(probe);

            if (invokerId != null) {
                if (genericProvider != null) {
                    String probeDescriptor = FlashlightProbe.getProbeDesc(moduleProviderName, moduleName, origProbeProviderName, probeName);
                    if (probeDescriptor != null) {
                        FlashlightProbe fp = genericProvider.getProbe(probeDescriptor);
                        if (fp != null) {
                             probe.setParent(fp);
                        }
                    }

                }
            }



    }

    public void unregisterProbeProvider(Object probeProvider) {
        try {
            ProbeProviderRegistry ppRegistry = ProbeProviderRegistry.getInstance();
            FlashlightProbeProvider fProbeProvider =
                    ppRegistry.getProbeProvider(probeProvider.getClass());
            ProbeRegistry probeRegistry = ProbeRegistry.getInstance();
            for (FlashlightProbe probe : fProbeProvider.getProbes()) {
                probeRegistry.unregisterProbe(probe);
            }
            ppRegistry.unregisterProbeProvider(probeProvider);
        } catch (Throwable t) {
            if (logger.isLoggable(Level.WARNING))
                logger.log(Level.WARNING, UNREGISTER_PROBE_PROVIDER_EXCEPTION, t);
        }
    }

    private  Class getGeneratedProbeProviderClass(Class oldProviderClazz, String invokerId) {
        Class genClazz = null;

        try {
            ProviderSubClassImplGenerator gen = new ProviderSubClassImplGenerator(
                    oldProviderClazz, invokerId);

            genClazz = gen.generateAndDefineClass(oldProviderClazz, invokerId);

            //System.out.println("** Loaded generated provider: " + genClazz.getName());
            return genClazz;
        } catch (Throwable cnfEx) {
            throw new RuntimeException(cnfEx);
        }
    }

    public void processXMLProbeProviders(ClassLoader cl, String xml, boolean inBundle) {
        if (logger.isLoggable(Level.FINE))
            logger.fine("processProbeProviderXML for " + xml);
        try {
            InputStream is;
            if (inBundle) {
                is = cl.getResourceAsStream(xml);
            } else {
                is = new FileInputStream(xml);
            }
            if (logger.isLoggable(Level.FINE))
                logger.fine("InputStream = " + is);
            ProbeProviderStaxParser providerXMLParser = new ProbeProviderStaxParser(is);
            List providers = providerXMLParser.getProviders();
            for (org.glassfish.flashlight.xml.Provider provider : providers) {
                if (logger.isLoggable(Level.FINE))
                    logger.fine(provider.toString());
                registerProvider(cl, provider);
            }
        } catch (Exception e) {
            Object params[] = {xml, e };
            logger.log(Level.SEVERE, CANNOT_PROCESS_XML_PROBE_PROVIDER, params);
        }

    }

    private  void notifyListenersOnAdd(String moduleProviderName, String moduleName,
                String probeProviderName, String invokerId,
                Class providerClazz, T provider) {
        for (ProbeProviderEventListener listener : listeners) {
            listener.probeProviderAdded(moduleProviderName, moduleName,
                probeProviderName, invokerId, providerClazz, provider);
        }
    }

    @Override
    public void addProbeProviderEventListener(ProbeProviderEventListener listener) {
        listeners.add(listener);
    }

    @Override
    public void removeProbeProviderEventListener(ProbeProviderEventListener listener) {
        listeners.remove(listener);
    }

    @Override
	public String toString() {
		return ObjectAnalyzer.toString(this);
	}


    private void handleDTrace(FlashlightProbeProvider provider) {
        // bnevins:  The way this works above (getProbeProvider()) is that every
        //**method** winds up added to the probe registry with an official ID.
        // I.e. a given provider-class generates possibly many probe objects
        // DTrace has a 1:1 correspondence between provider class and dtrace class imp
        // So we loop through all the probes and add the same DTrace impl object to
        // each probe.
        // We set the DTrace Method object inside the probe just this once to avoid
        // having to discover it anew over and over and over again at runtime...

		if(allHidden(provider))
			return;  // no need to waste time if they are all hidden

        DTraceContract dt = FlashlightUtils.getDtraceEngine();

        // is DTrace available and enabled?
        if(dt == null)
            return;

        // here is a way to do the same thing but you get the intermediate interface class
        //Class dtraceProviderInterface = dt.getInterface(provider);
        //Object dtraceProviderImpl = dt.getProvider(dtraceProviderInterface);

        Object dtraceProviderImpl = dt.getProvider(provider);

        // something is wrong with the provider class
        if(dtraceProviderImpl == null) {
            provider.setDTraceInstrumented(false);
            return;
        }

        provider.setDTraceInstrumented(true);

         Collection probes = provider.getProbes();
         boolean onlyHidden = true;

         for(FlashlightProbe probe : probes) {
             // if it is hidden -- do not hook-up a DTrace "listener"

             if(!probe.isHidden()) {
                 DTraceMethodFinder mf = new DTraceMethodFinder(probe, dtraceProviderImpl);
                 probe.setDTraceMethod(mf.matchMethod());
                 probe.setDTraceProviderImpl(dtraceProviderImpl);
                 onlyHidden = false;    // we have at least one!
             }
         }

         // if there are only hidden probes -- don't register the class

         if(!onlyHidden)
            FlashlightProbeClientMediator.getInstance().registerDTraceListener(provider);
    }



    private boolean allHidden(FlashlightProbeProvider provider) {
        for(FlashlightProbe probe : provider.getProbes())
            if(!probe.isHidden())
                return false;   // at least one is not hidden

        return true;
    }


    private void registerProvider(ClassLoader cl, org.glassfish.flashlight.xml.Provider provider) {

        String moduleProviderName = provider.getModuleProviderName();
        String moduleName = provider.getModuleName();
        String probeProviderName = provider.getProbeProviderName();
        String providerClass = provider.getProbeProviderClass();
        List probes = provider.getProbes();
        Class providerClazz = null;

        try {
            providerClazz = cl.loadClass(providerClass);
            if (logger.isLoggable(Level.FINE))
                logger.fine("providerClazz = " + providerClazz);
        } catch (Exception e) {
            if (logger.isLoggable(Level.FINE))
                logger.fine( " Could not load the class ( " + providerClazz +
                        " ) for the provider " + providerClass);
            e.printStackTrace();
        }
        if (logger.isLoggable(Level.FINE)) {
            logger.fine("moduleProviderName = " + moduleProviderName);
            logger.fine("moduleName = " + moduleName);
            logger.fine("probeProviderName = " + probeProviderName);
            logger.fine("probeProviderClass = " + providerClass);
        }
        FlashlightProbeProvider flProvider = new FlashlightProbeProvider(
            		moduleProviderName, moduleName, probeProviderName, providerClazz);

        for (org.glassfish.flashlight.xml.XmlProbe probe : probes) {
            String probeName = probe.getProbeName();
            String probeMethod = probe.getProbeMethod();
            boolean hasSelf = probe.hasSelf();
            boolean isHidden = probe.isHidden();

            boolean errorParsingProbe = false;
            String[] probeParams = new String[probe.getProbeParams().size()];
            Class[] paramTypes = new Class[probe.getProbeParams().size()];

            int i = 0;
            for (org.glassfish.flashlight.xml.XmlProbeParam param : probe.getProbeParams()) {
                probeParams[i] = param.getName();
                if (logger.isLoggable(Level.FINE))
                    logger.fine("          probeParam[" + i + "] = " + probeParams[i]);
                paramTypes[i] = getParamType(cl, param.getType());

                if (paramTypes[i] == null) {
                    // Lets not create a probe if we see a problem with the
                    // paramType resolution
                    errorParsingProbe = true;
                    logger.log(Level.SEVERE, CANNOT_RESOLVE_PROBE_PARAM_TYPES_FOR_PROBE, new Object[] {probeName});
                    // stop parsing anymore probe params
                    break;
                }

                i++;
            }
            if (errorParsingProbe) {
                //reset
                errorParsingProbe = false;
                // continue for the next probe
                continue;
            }
            FlashlightProbe flProbe = ProbeFactory.createProbe( providerClazz,
                    moduleProviderName, moduleName, probeProviderName, probeName,
                    probeParams, paramTypes, hasSelf, isHidden,
                    probe.getStateful(), probe.getStatefulReturn(), probe.getStatefulException(),
                    splitProfileNames(probe.getProfileNames()));
            flProbe.setProviderJavaMethodName(probeMethod);
            if (logger.isLoggable(Level.FINE))
                logger.fine(" Constructed probe = " + flProbe.toString());
            flProvider.addProbe(flProbe);
        }
        if (flProvider.getProbes().size() == 0)
            return;

        handleDTrace(flProvider);
        allProbeProviders.add(flProvider);
        ProbeProviderRegistry.getInstance().registerProbeProvider(
                flProvider, providerClazz);
        if (logger.isLoggable(Level.FINE))
            logger.fine (" Provider registered successfully - " + probeProviderName);
   }


    private Class getParamType(ClassLoader cl, String paramTypeStr) {
        Class paramType = null;

        try {
            // Lets see if this is a primitive type
            Class primType = primTypes.get(paramTypeStr);
            if (primType != null) {
                return primType;
            }
            //Not a primitive type, lets try to load it as is
            paramType = cl.loadClass(paramTypeStr);

        } catch (ClassNotFoundException ex) {
            try {
                // Not a primitive or the actual type, maybe its one of the java.lang.* types
                // try to prepend java.lang. to the given class
                paramType = cl.loadClass("java.lang." + paramTypeStr);
            } catch (Exception e) {
                Object params[] = {paramTypeStr, e};
                logger.log(Level.SEVERE, CANNOT_RESOLVE_PROBE_PARAM_TYPES, params);
            }
        }

        if (logger.isLoggable(Level.FINE))
            logger.fine("          paramType = " + paramType);

        return paramType;

    }

    private boolean isValidString(String str) {
        if ((str != null) && (str.length() > 0)){
            return true;
        }
        return false;
    }
    
    private String [] splitProfileNames(String profileNamesAll) {
        if (profileNamesAll == null)
            return null;
        String [] profileNames = profileNamesAll.split(",");
        for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy