![JAR search and dependency download from the Maven repository](/logo.png)
com.tsc9526.monalisa.tools.agent.AgentClass Maven / Gradle / Ivy
/*******************************************************************************************
* Copyright (c) 2016, zzg.zhou([email protected])
*
* Monalisa is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*******************************************************************************************/
package com.tsc9526.monalisa.tools.agent;
import java.io.File;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import com.tsc9526.monalisa.orm.datasource.DbProp;
import com.tsc9526.monalisa.tools.PkgNames;
import com.tsc9526.monalisa.tools.Tasks;
import com.tsc9526.monalisa.tools.clazz.CompilePackage;
import com.tsc9526.monalisa.tools.clazz.Compiler;
import com.tsc9526.monalisa.tools.clazz.MelpClass;
import com.tsc9526.monalisa.tools.clazz.MelpClasspath;
import com.tsc9526.monalisa.tools.clazz.MelpLib;
import com.tsc9526.monalisa.tools.io.MelpFile;
import com.tsc9526.monalisa.tools.json.MelpJson;
import com.tsc9526.monalisa.tools.logger.Logger;
import com.tsc9526.monalisa.tools.misc.MelpException;
import com.tsc9526.monalisa.tools.string.MelpDate;
/**
*
* @author zzg.zhou([email protected])
*/
public class AgentClass {
static Logger logger=Logger.getLogger(AgentClass.class);
static Map hAgentClasses=new ConcurrentHashMap();
public static void premain(String agentArgs, Instrumentation inst){
//agentmain(agentArgs,inst);
}
public static void agentmain(String agentArgs,Instrumentation inst) {
try{
Class.forName(PkgNames.ORM_JSONHELPER);
}catch(ClassNotFoundException e){
delegateAgent(agentArgs,inst);
return;
}catch(NoClassDefFoundError e){
delegateAgent(agentArgs,inst);
return;
}
callAgent(agentArgs,inst);
}
private static void delegateAgent(final String agentArgs,final Instrumentation inst){
try{
for(Class> c:inst.getAllLoadedClasses()){
if(c.getName().equals(PkgNames.ORM_AGENTCLASS)){
Method m=c.getMethod("agentmain", String.class,Instrumentation.class);
m.invoke(null, agentArgs,inst);
break;
}
}
}catch(Exception e){
MelpException.throwRuntimeException(e);
}
}
private static void callAgent(final String argsReloadFilePath,final Instrumentation inst){
try {
File f=new File(argsReloadFilePath);
String json=MelpFile.readToString(f,"utf-8");
File to=new File(argsReloadFilePath+"ed");
if(to.exists()){
to.delete();
}
f.renameTo(to);
AgentArgs args=MelpJson.getGson().fromJson(json, AgentArgs.class);
printAgentInfo(args);
for(AgentArgs.AgentArgClassInfo ci:args.getClasses()){
String classFilePath=getClassFilePath(args.getClassFilePathRoot(),ci.className);
byte[] classBytes = MelpFile.readFile(classFilePath);
redefineClass(inst,ci.className,classBytes);
hAgentClasses.put(ci.className, ci);
}
} catch (Exception e) {
MelpException.throwRuntimeException(e);
}
}
private static void printAgentInfo(AgentArgs args){
StringBuffer sb=new StringBuffer();
for(AgentArgs.AgentArgClassInfo ci:args.getClasses()){
AgentArgs.AgentArgClassInfo old=hAgentClasses.get(ci.className);
long oldVersion =old!=null?old.version:MelpClass.getVersion(ci.className);
long oldLastModified=old!=null?old.lastModified:MelpClasspath.getClassOrJarFile(ci.className).lastModified();
String oldTs=MelpDate.toString(new Date(oldLastModified),"yyyyMMddHHmmss");
String newTs=MelpDate.toString(new Date(ci.lastModified),"yyyyMMddHHmmss");
if(old==null){
if(ci.version ");
}else if(ci.lastModified ");
}else{
sb.append("* ");
}
}
String sv=(ci.version ==oldVersion ?" == ":(ci.version >oldVersion ?" -> ":" -< "));
String st=(ci.lastModified==oldLastModified?" == ":(ci.lastModified>oldLastModified?" -> ":" -< "));
sb.append("class: "+ci.className);
sb.append(", version: " +oldVersion+sv+ci.version );
sb.append(", timestamp: " +oldTs +st+newTs );
sb.append(", file: "+ci.javaFilePath);
sb.append("\r\n");
}
logger.info("Reload classes: "+args.getClasses().length
+"\r\n***************************************************************************************************"
+"\r\n* Source root path: "+new File(args.getSourceFilePathRoot()).getAbsolutePath()
+"\r\n* Class root path: "+new File(args.getClassFilePathRoot()).getAbsolutePath()
+"\r\n* ================================================================================================="
+"\r\n"+sb.toString()
+ "***************************************************************************************************");
}
public static AgentArgs.AgentArgClassInfo getAgentLoadClassInfo(String className) {
return hAgentClasses.get(className);
}
private static void redefineClass(Instrumentation inst,String className,byte[] classBytes)throws Exception{
ClassDefinition reporterDef = new ClassDefinition(Class.forName(className), classBytes);
inst.redefineClasses(reporterDef);
}
private static String getClassFilePath(String classFilePathRoot,String className){
String path=classFilePathRoot;
if(!path.endsWith("/")){
path+="/";
}
path+=className.replace(".","/")+".class";
return path;
}
private static boolean initilized=false;
private synchronized static void initAgentClasses(){
if(!initilized){
reloadClasses();
long delay=DbProp.CFG_RELOAD_CLASS_INTERVAL*1000;
Tasks.instance.addSchedule("ClassReloadTask", new TimerTask() {
public void run() {
reloadClasses();
}
}, delay, delay);
initilized=true;
}
}
private static CompilePackage compilePackage;
public synchronized static void reloadClasses(){
if(compilePackage==null){
compilePackage=new CompilePackage(DbProp.CFG_AGENT_PATH,DbProp.TMP_WORK_DIR_JAVA);
if (ClassLoader.getSystemClassLoader() != AgentClass.class.getClassLoader()){
MelpClasspath.appendToSystemPath(AgentClass.class);
}
}
try{
Compiler.compile(compilePackage);
List cis=new ArrayList();
for(AgentJavaFile j:compilePackage.getJavaFiles()){
if(j.isReloadRequired()){
cis.add(new AgentArgs.AgentArgClassInfo(j));
}
}
if(cis.size()>0){
AgentArgs args=new AgentArgs(DbProp.CFG_AGENT_PATH,DbProp.TMP_WORK_DIR_JAVA,cis.toArray(new AgentArgs.AgentArgClassInfo[0]));
String agentArgs=MelpJson.createGsonBuilder().setPrettyPrinting().create().toJson(args);
File f=new File(DbProp.CFG_AGENT_PATH,".load");
MelpFile.write(f,agentArgs.getBytes("utf-8") );
AgentJar.loadAgentClass(AgentClass.class.getName(), MelpFile.combinePath(f.getAbsolutePath()));
}
}catch(Exception e){
logger.error("Reload exception: "+e,e);
}
}
public static T createAgent(Class theClass){
if(Modifier.isFinal(theClass.getModifiers())){
throw new RuntimeException("Agent class: "+theClass.getName()+" cannot be marked by final!");
}
try {
if(!initilized){
MelpLib.tryLoadGson();
initAgentClasses();
}
T value=MelpLib.createAgentEnhancer().createProxyInstance(theClass);
return value;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy