package scouter.agent.plugin;
import scouter.agent.Logger;
import scouter.agent.netio.data.DataProxy;
import scouter.agent.trace.AlertProxy;
import scouter.agent.trace.HookArgs;
import scouter.agent.trace.TraceContext;
import scouter.agent.trace.TransferMap;
import scouter.lang.AlertLevel;
import scouter.lang.pack.XLogTypes;
import scouter.lang.step.ApiCallStep;
import scouter.lang.step.ThreadSubmitStep;
import scouter.util.KeyGen;
import scouter.util.SysJMX;
import java.lang.reflect.*;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
public class AbstractPlugin {
private static Map<String, AccessibleObject> reflCache = Collections.synchronizedMap(new LinkedHashMap<String, AccessibleObject>(100));
long lastModified;
public void log(Object c) {
Logger.println("A158", c.toString());
}
public void println(Object c) {
System.out.println(c);
}
public static Object invokeMethod(Object o, String methodName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Object[] objs = {};
return invokeMethod(o, methodName, objs);
}
public static Object invokeMethod(Object o, String methodName, Object... args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
int argsSize = args.length;
StringBuilder signature = new StringBuilder(o.getClass().getName()).append(":").append(methodName).append("():");
Class[] argClazzes = new Class[argsSize];
for(int i=0; i<argsSize; i++) {
argClazzes[i] = args[i].getClass();
signature.append(argClazzes[i].getName()).append("+");
}
Method m = (Method) reflCache.get(signature.toString());
if(m == null) {
m = o.getClass().getMethod(methodName, argClazzes);
reflCache.put(signature.toString(), m);
}
return m.invoke(o, args);
}
public static Object newInstance(String className) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
return newInstance(className, Thread.currentThread().getContextClassLoader());
}
public static Object newInstance(String className, ClassLoader loader) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Object[] objs = {};
return newInstance(className, loader, objs);
}
public static Object newInstance(String className, Object... args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
return newInstance(className, Thread.currentThread().getContextClassLoader(), args);
}
public static Object newInstance(String className, ClassLoader loader, Object... args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
int argsSize = args.length;
Class[] argClazzes = new Class[argsSize];
StringBuilder signature = new StringBuilder(className).append(":<init>:");
for(int i=0; i<argsSize; i++) {
argClazzes[i] = args[i].getClass();
signature.append(argClazzes[i].getName()).append("+");
}
Class clazz = Class.forName(className, true, loader);
Constructor constructor = (Constructor)reflCache.get(signature.toString());
if(constructor == null) {
constructor = clazz.getConstructor(argClazzes);
reflCache.put(signature.toString(), constructor);
}
return constructor.newInstance(args);
}
public static Object getFieldValue(Object o, String fieldName) throws InvocationTargetException, IllegalAccessException, NoSuchFieldException {
StringBuilder signature = new StringBuilder(o.getClass().getName()).append(":").append(fieldName).append(":");
Field f = (Field) reflCache.get(signature.toString());
if(f == null) {
f = o.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
reflCache.put(signature.toString(), f);
}
return f.get(o);
}
@Deprecated
public Object field(Object o, String field) {
if (o == null)
return null;
try {
Field f = o.getClass().getDeclaredField(field);
f.setAccessible(true);
return f.get(o);
} catch (Throwable e) {
}
return null;
}
@Deprecated
public Object method(Object o, String method) {
if (o == null)
return null;
try {
Method m = o.getClass().getMethod(method, Wrapper.arg_c);
m.setAccessible(true);
return m.invoke(o, Wrapper.arg_o);
} catch (Throwable e) {
}
return null;
}
@Deprecated
public Object method1(Object o, String method) {
if (o == null)
return null;
try {
Method m = o.getClass().getMethod(method, Wrapper.arg_c);
return m.invoke(o, Wrapper.arg_o);
} catch (Throwable e) {
return e.toString();
}
}
@Deprecated
public Object method(Object o, String method, String param) {
if (o == null)
return null;
try {
Method m = o.getClass().getMethod(method, Wrapper.arg_c_s);
return m.invoke(o, new Object[] { param });
} catch (Throwable e) {
}
return null;
}
public String toString(Object o) {
return o == null ? null : o.toString();
}
public String toString(Object o, String def) {
return o == null ? def : o.toString();
}
public void alert(char level, String title, String message) {
switch (level) {
case 'i':
case 'I':
AlertProxy.sendAlert(AlertLevel.INFO, title, message);
case 'w':
case 'W':
AlertProxy.sendAlert(AlertLevel.WARN, title, message);
break;
case 'e':
case 'E':
AlertProxy.sendAlert(AlertLevel.ERROR, title, message);
break;
case 'f':
case 'F':
AlertProxy.sendAlert(AlertLevel.FATAL, title, message);
break;
}
}
///
public int syshash(Object o) {
if (o == null)
return 0;
return System.identityHashCode(o);
}
public int syshash(HookArgs hook, int x) {
if (x >= hook.args.length)
return 0;
return syshash(hook.args[x]);
}
public int syshash(HookArgs hook) {
if (hook == null || hook.this1 == null)
return 0;
return syshash(hook.this1);
}
public void forward(WrContext wctx, int uuid) {
TraceContext ctx = wctx.inner();
if (ctx.gxid == 0) {
ctx.gxid = ctx.txid;
}
long callee = KeyGen.next();
TransferMap.put(uuid, ctx.gxid, ctx.txid, callee, XLogTypes.APP_SERVICE);
ApiCallStep step = new ApiCallStep();
step.txid = callee;
step.start_time = (int) (System.currentTimeMillis() - ctx.startTime);
if (ctx.profile_thread_cputime) {
step.start_cpu = (int) (SysJMX.getCurrentThreadCPU() - ctx.startCpu);
}
step.hash = DataProxy.sendApicall("local-forward");
ctx.profile.add(step);
}
public void forwardThread(WrContext wctx, int uuid) {
if (wctx == null)
return;
TraceContext ctx = wctx.inner();
if (ctx.gxid == 0) {
ctx.gxid = ctx.txid;
}
long callee = KeyGen.next();
TransferMap.put(uuid, ctx.gxid, ctx.txid, callee, XLogTypes.BACK_THREAD);
ThreadSubmitStep step = new ThreadSubmitStep();
step.txid = callee;
step.start_time = (int) (System.currentTimeMillis() - ctx.startTime);
if (ctx.profile_thread_cputime) {
step.start_cpu = (int) (SysJMX.getCurrentThreadCPU() - ctx.startCpu);
}
step.hash = DataProxy.sendApicall("local-forward");
ctx.profile.add(step);
}
public void receive(WrContext ctx, int uuid) {
TransferMap.ID id = TransferMap.get(uuid);
if (id == null)
return;
TransferMap.remove(uuid);
if (id.gxid != 0) {
ctx.inner().gxid = id.gxid;
}
if (id.callee != 0) {
ctx.inner().txid = id.callee;
}
if (id.caller != 0) {
ctx.inner().caller = id.caller;
}
ctx.inner().xType = id.xType;
}
}