org.glassfish.flashlight.impl.client.FlashlightProbeClientMediator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-micro Show documentation
Show all versions of payara-micro Show documentation
Micro Distribution of the Payara Project
/*
* 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;
}
}