mirror of https://github.com/mchr3k/org.intrace
Rename project
This commit is contained in:
parent
04c75566c0
commit
88e5f63ab9
|
|
@ -1,5 +0,0 @@
|
|||
Manifest-Version: 1.0
|
||||
Premain-Class: gb.instrument.agent.Agent
|
||||
Agent-Class: gb.instrument.agent.Agent
|
||||
Can-Redefine-Classes: true
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="lib" path="lib/asm-2.2.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/asm-commons-2.2.3.jar"/>
|
||||
<classpathentry kind="lib" path="C:/Program Files/Java/jdk1.6.0/lib/tools.jar"/>
|
||||
<classpathentry kind="con" path="SWT_CONTAINER"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.intrace</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.jem.beaninfo.BeanInfoNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#Thu Nov 05 12:58:44 GMT 2009
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,64 @@
|
|||
<project name="TraceAgent" basedir="." default="help">
|
||||
<target name="help">
|
||||
<java classname="org.apache.tools.ant.Main">
|
||||
<arg value="-projecthelp" />
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<target name="build" depends="buildClasses, createJar, deploy" />
|
||||
|
||||
<target name="buildClasses" description="Comile classes">
|
||||
<delete dir="./bin" includes="**/*" />
|
||||
<mkdir dir="./bin" />
|
||||
|
||||
<javac srcdir="./src" destdir="./bin" debug="true" source="1.6" target="1.6" nowarn="true">
|
||||
<classpath>
|
||||
<fileset dir="./lib" includes="*.jar" erroronmissingdir="false" />
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="createJar" description="Create the Agent Jar">
|
||||
<delete dir="./lib/libclasses" includes="**/*" />
|
||||
<mkdir dir="./lib/libclasses" />
|
||||
<unzip src="./lib/asm-2.2.3.jar" dest="./lib/libclasses">
|
||||
<patternset>
|
||||
<include name="**/*.class" />
|
||||
<exclude name="META-INF" />
|
||||
</patternset>
|
||||
</unzip>
|
||||
<unzip src="./lib/asm-commons-2.2.3.jar" dest="./lib/libclasses">
|
||||
<patternset>
|
||||
<include name="**/EmptyVisitor.class" />
|
||||
<exclude name="META-INF" />
|
||||
</patternset>
|
||||
</unzip>
|
||||
|
||||
<mkdir dir="./built/" />
|
||||
<jar destfile="./built/traceagent.jar" compress="false" manifest="conf/META-INF/MANIFEST.MF">
|
||||
<fileset dir="./bin" includes="**/agent/**/*.class" />
|
||||
<fileset dir="./bin" includes="**/output/**/*.class" />
|
||||
<fileset dir="./lib/libclasses" includes="**/*.class" />
|
||||
</jar>
|
||||
<jar destfile="./built/cuitraceclient.jar" compress="false">
|
||||
<fileset dir="./bin" includes="**/output/trace/TraceConfigConstants.class" />
|
||||
<fileset dir="./bin" includes="**/agent/AgentConfigConstants.class" />
|
||||
<fileset dir="./bin" includes="**/client/cui/**/*.class" />
|
||||
</jar>
|
||||
<jar destfile="./built/guitraceclient.jar" filesetmanifest="mergewithoutmain">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="gb.instrument.client.gui.TraceClient" />
|
||||
<attribute name="Class-Path" value="." />
|
||||
</manifest>
|
||||
<fileset dir="./bin" includes="**/output/trace/TraceSettingsConstants.class" />
|
||||
<fileset dir="./bin" includes="**/agent/AgentConfigConstants.class" />
|
||||
<fileset dir="./bin" includes="**/client/gui/**/*.class" />
|
||||
<zipfileset excludes="META-INF/*.SF" src="lib/org.eclipse.swt.win32.win32.x86_3.5.2.v3557f.jar" />
|
||||
</jar>
|
||||
<delete dir="./lib/libclasses" includes="**/*" />
|
||||
</target>
|
||||
|
||||
<target name="deploy" description="Copy agent jar to another project">
|
||||
<copy file="./built/traceagent.jar" tofile="../TestProject/lib/traceagent.jar" overwrite="true" />
|
||||
</target>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Manifest-Version: 1.0
|
||||
Premain-Class: org.intrace.agent.Agent
|
||||
Agent-Class: org.intrace.agent.Agent
|
||||
Can-Redefine-Classes: true
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,58 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
|
||||
import org.intrace.agent.server.AgentServer;
|
||||
|
||||
/**
|
||||
* Trace Agent: Installs a Class Transformer to add trace lines.
|
||||
*/
|
||||
public class Agent
|
||||
{
|
||||
/**
|
||||
* Agent called on JVM init.
|
||||
* @param agentArgs
|
||||
* @param inst
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void premain(String agentArgs, Instrumentation inst) throws IOException
|
||||
{
|
||||
initialize(agentArgs, inst);
|
||||
}
|
||||
|
||||
/**
|
||||
* Agent called after JVM init.
|
||||
* @param agentArgs
|
||||
* @param inst
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void agentmain(String agentArgs, Instrumentation inst) throws IOException
|
||||
{
|
||||
initialize(agentArgs, inst);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common init function.
|
||||
* @param agentArgs
|
||||
* @param inst
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void initialize(String agentArgs, Instrumentation inst) throws IOException
|
||||
{
|
||||
System.out.println("Loaded Tracing Agent.");
|
||||
|
||||
AgentSettings args = new AgentSettings(agentArgs);
|
||||
AgentHelper.getActiveOutputHandler().getResponse(agentArgs);
|
||||
|
||||
ClassTransformer t = new ClassTransformer(inst, args);
|
||||
inst.addTransformer(t, true);
|
||||
t.traceLoadedClasses();
|
||||
|
||||
Thread traceServer = new Thread(new AgentServer(t));
|
||||
traceServer.setName("TraceServer");
|
||||
traceServer.setDaemon(true);
|
||||
traceServer.start();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
public class AgentConfigConstants
|
||||
{
|
||||
public static final String CLASS_REGEX = "AGENT_CLASS_REGEX";
|
||||
public static final String TRACING_ENABLED = "AGENT_TRACING_ENABLED";
|
||||
public static final String SAVE_TRACED_CLASSFILES = "AGENT_SAVE_TRACED_CLASSFILES";
|
||||
public static final String VERBOSE_MODE = "AGENT_VERBOSE_MODE";
|
||||
public static final String ALLOW_JARS_TO_BE_TRACED = "AGENT_LLOW_JARS_TO_BE_TRACED";
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
import org.intrace.output.IOutput;
|
||||
import org.intrace.output.trace.TraceOutput;
|
||||
|
||||
|
||||
/**
|
||||
* Static implementation of the TraceWriter interface
|
||||
*/
|
||||
public class AgentHelper
|
||||
{
|
||||
private static IOutput outputHandler = new TraceOutput();
|
||||
|
||||
public static IOutput getActiveOutputHandler()
|
||||
{
|
||||
return outputHandler;
|
||||
}
|
||||
|
||||
public static void enter(String className, String methodName)
|
||||
{
|
||||
outputHandler.enter(className, methodName);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, byte byteArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, byteArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, byte[] byteArrayArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, byteArrayArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, short shortArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, shortArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, short[] shortArrayArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, shortArrayArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, int intArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, intArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, int[] intArrayArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, intArrayArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, long longArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, longArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, long[] longArrayArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, longArrayArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, float floatArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, floatArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, float[] floatArrayArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, floatArrayArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, double doubleArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, doubleArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, double[] doubleArrayArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, doubleArrayArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, boolean boolArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, boolArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, boolean[] boolArrayArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, boolArrayArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, char charArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, charArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, char[] charArrayArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, charArrayArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, Object objArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, objArg);
|
||||
}
|
||||
|
||||
public static void arg(String className, String methodName, Object[] objArrayArg)
|
||||
{
|
||||
outputHandler.arg(className, methodName, objArrayArg);
|
||||
}
|
||||
|
||||
public static void branch(String className, String methodName, int lineNo)
|
||||
{
|
||||
outputHandler.branch(className, methodName, lineNo);
|
||||
}
|
||||
|
||||
public static void exit(String className, String methodName, int lineNo)
|
||||
{
|
||||
outputHandler.exit(className, methodName, lineNo);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Args Format:
|
||||
* "[arg1[arg2[arg3"
|
||||
*
|
||||
* where argx is of the form
|
||||
* value-parameter
|
||||
*/
|
||||
public class AgentSettings
|
||||
{
|
||||
private Pattern classRegex = Pattern.compile("");
|
||||
private boolean tracingEnabled = false;
|
||||
private boolean saveTracedClassfiles = false;
|
||||
private boolean verboseMode = false;
|
||||
private boolean allowJarsToBeTraced = false;
|
||||
|
||||
public AgentSettings(String args)
|
||||
{
|
||||
parseArg(args);
|
||||
}
|
||||
|
||||
public AgentSettings(AgentSettings oldInstance)
|
||||
{
|
||||
classRegex = oldInstance.getClassRegex();
|
||||
tracingEnabled = oldInstance.isTracingEnabled();
|
||||
saveTracedClassfiles = oldInstance.saveTracedClassfiles();
|
||||
verboseMode = oldInstance.isVerboseMode();
|
||||
allowJarsToBeTraced = oldInstance.allowJarsToBeTraced();
|
||||
}
|
||||
|
||||
public void parseArgs(String args)
|
||||
{
|
||||
String[] seperateArgs = args.split("\\[");
|
||||
for (int ii = 0; ii < seperateArgs.length; ii++)
|
||||
{
|
||||
parseArg(seperateArgs[ii].toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
private void parseArg(String arg)
|
||||
{
|
||||
if (arg.equals("verbose-true"))
|
||||
{
|
||||
verboseMode = true;
|
||||
}
|
||||
else if (arg.equals("verbose-false"))
|
||||
{
|
||||
verboseMode = false;
|
||||
}
|
||||
else if (arg.equals("instru-true"))
|
||||
{
|
||||
tracingEnabled = true;
|
||||
}
|
||||
else if (arg.equals("instru-false"))
|
||||
{
|
||||
tracingEnabled = false;
|
||||
}
|
||||
else if (arg.equals("saveinstru-true"))
|
||||
{
|
||||
saveTracedClassfiles = true;
|
||||
}
|
||||
else if (arg.equals("saveinstru-false"))
|
||||
{
|
||||
saveTracedClassfiles = false;
|
||||
}
|
||||
else if (arg.equals("instrujars-true"))
|
||||
{
|
||||
allowJarsToBeTraced = true;
|
||||
}
|
||||
else if (arg.equals("instrujars-false"))
|
||||
{
|
||||
allowJarsToBeTraced = false;
|
||||
}
|
||||
else if (arg.startsWith("regex-"))
|
||||
{
|
||||
String classRegexStr = arg.replace("regex-", "");
|
||||
classRegex = Pattern.compile(classRegexStr);
|
||||
}
|
||||
}
|
||||
|
||||
public Pattern getClassRegex()
|
||||
{
|
||||
return classRegex;
|
||||
}
|
||||
|
||||
public boolean isTracingEnabled()
|
||||
{
|
||||
return tracingEnabled;
|
||||
}
|
||||
|
||||
public boolean saveTracedClassfiles()
|
||||
{
|
||||
return saveTracedClassfiles;
|
||||
}
|
||||
|
||||
public boolean isVerboseMode()
|
||||
{
|
||||
return verboseMode;
|
||||
}
|
||||
|
||||
public boolean allowJarsToBeTraced()
|
||||
{
|
||||
return allowJarsToBeTraced;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String currentSettings = "";
|
||||
currentSettings += "Class Regex : " + classRegex + "\n";
|
||||
currentSettings += "Tracing Enabled : " + tracingEnabled + "\n";
|
||||
currentSettings += "Save Traced Class Files : " + saveTracedClassfiles + "\n";
|
||||
currentSettings += "Trace Classes in JAR Files : " + allowJarsToBeTraced + "\n";
|
||||
return currentSettings;
|
||||
}
|
||||
|
||||
public Map<String,String> getSettingsMap()
|
||||
{
|
||||
Map<String,String> settingsMap = new HashMap<String, String>();
|
||||
settingsMap.put(AgentConfigConstants.TRACING_ENABLED, Boolean.toString(tracingEnabled));
|
||||
settingsMap.put(AgentConfigConstants.CLASS_REGEX, classRegex.pattern());
|
||||
settingsMap.put(AgentConfigConstants.ALLOW_JARS_TO_BE_TRACED, Boolean.toString(allowJarsToBeTraced));
|
||||
settingsMap.put(AgentConfigConstants.VERBOSE_MODE, Boolean.toString(verboseMode));
|
||||
settingsMap.put(AgentConfigConstants.SAVE_TRACED_CLASSFILES, Boolean.toString(saveTracedClassfiles));
|
||||
return settingsMap;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.GOTO;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.commons.EmptyVisitor;
|
||||
|
||||
/**
|
||||
* First pass analysis phase
|
||||
*/
|
||||
public class ClassBranchLineAnalysis extends EmptyVisitor
|
||||
{
|
||||
private Map<String, Set<Integer>> methodBranchTraceLines = new HashMap<String, Set<Integer>>();
|
||||
private Set<Integer> branchTraceLines = new HashSet<Integer>();
|
||||
private Map<Label,Integer> methodLabelLineNos = new HashMap<Label,Integer>();
|
||||
private String methodSig;
|
||||
private boolean traceThisLine = false;
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
|
||||
{
|
||||
methodLabelLineNos.clear();
|
||||
methodSig = name + desc;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumber(int xiLineNo, Label xiLabel)
|
||||
{
|
||||
methodLabelLineNos.put(xiLabel, xiLineNo);
|
||||
if (traceThisLine)
|
||||
{
|
||||
branchTraceLines.add(xiLineNo);
|
||||
traceThisLine = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJumpInsn(int xiOpCode, Label xiBranchLabel)
|
||||
{
|
||||
if (xiOpCode != GOTO)
|
||||
{
|
||||
traceThisLine= true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Integer lineNo = methodLabelLineNos.get(xiBranchLabel);
|
||||
if (lineNo != null)
|
||||
{
|
||||
branchTraceLines.add(lineNo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd()
|
||||
{
|
||||
if (methodSig != null)
|
||||
{
|
||||
methodBranchTraceLines.put(methodSig, branchTraceLines);
|
||||
methodSig = null;
|
||||
branchTraceLines = new HashSet<Integer>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Analysis data.
|
||||
*/
|
||||
public Map<String, Set<Integer>> getMethodBranchLabels()
|
||||
{
|
||||
return methodBranchTraceLines;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.instrument.ClassFileTransformer;
|
||||
import java.lang.instrument.IllegalClassFormatException;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.lang.instrument.UnmodifiableClassException;
|
||||
import java.security.CodeSource;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
|
||||
/**
|
||||
* Uses ASM2 to transform class files to add Trace output.
|
||||
*/
|
||||
public class ClassTransformer implements ClassFileTransformer
|
||||
{
|
||||
/**
|
||||
* Map of modified class names to their original bytes
|
||||
*/
|
||||
private final Set<String> modifiedClasses =
|
||||
new ConcurrentSkipListSet<String>();
|
||||
private final Instrumentation inst;
|
||||
private final AgentSettings args;
|
||||
|
||||
/**
|
||||
* cTor
|
||||
* @param xiInst
|
||||
* @param xiEnableTracing
|
||||
* @param xiClassRegex
|
||||
* @param xiWriteModifiedClassfiles
|
||||
* @param xiVerboseMode
|
||||
* @param xiEnableTraceJars
|
||||
*/
|
||||
public ClassTransformer(Instrumentation xiInst, AgentSettings xiArgs)
|
||||
{
|
||||
inst = xiInst;
|
||||
args = xiArgs;
|
||||
if (args.isVerboseMode())
|
||||
{
|
||||
System.out.println(args.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle whether tracing is enabled
|
||||
* @param xiTracingEnabled
|
||||
*/
|
||||
public void setTracingEnabled(boolean xiOldTracingEnabled)
|
||||
{
|
||||
if (args.isTracingEnabled() && !xiOldTracingEnabled)
|
||||
{
|
||||
traceLoadedClasses();
|
||||
}
|
||||
else if (!args.isTracingEnabled() && xiOldTracingEnabled)
|
||||
{
|
||||
recheckModifiedClasses();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply Trace transformation to loaded classes.
|
||||
* @param xiInst
|
||||
*/
|
||||
public void traceLoadedClasses()
|
||||
{
|
||||
Class<?>[] loadedClasses = inst.getAllLoadedClasses();
|
||||
for (Class<?> loadedClass : loadedClasses)
|
||||
{
|
||||
if (loadedClass.isAnnotation())
|
||||
{
|
||||
if (args.isVerboseMode())
|
||||
{
|
||||
System.out.println("Ignoring annotation class: " + loadedClass.getCanonicalName());
|
||||
}
|
||||
}
|
||||
else if (loadedClass.isSynthetic())
|
||||
{
|
||||
if (args.isVerboseMode())
|
||||
{
|
||||
System.out.println("Ignoring synthetic class: " + loadedClass.getCanonicalName());
|
||||
}
|
||||
}
|
||||
else if (!inst.isModifiableClass(loadedClass))
|
||||
{
|
||||
if (args.isVerboseMode())
|
||||
{
|
||||
System.out.println("Ignoring unmodifiable class: " + loadedClass.getCanonicalName());
|
||||
}
|
||||
}
|
||||
else if (args.isTracingEnabled() &&
|
||||
isToBeConsideredForCoverage(loadedClass.getName(), loadedClass.getProtectionDomain()))
|
||||
{
|
||||
try
|
||||
{
|
||||
inst.retransformClasses(loadedClass);
|
||||
}
|
||||
catch (UnmodifiableClassException e)
|
||||
{
|
||||
// Write exception to stdout
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore original class bytes
|
||||
* @param xiInst
|
||||
*/
|
||||
private void recheckModifiedClasses()
|
||||
{
|
||||
Class<?>[] loadedClasses = inst.getAllLoadedClasses();
|
||||
for (Class<?> loadedClass : loadedClasses)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (modifiedClasses.contains(loadedClass.getName()))
|
||||
{
|
||||
inst.retransformClasses(loadedClass);
|
||||
}
|
||||
}
|
||||
catch (UnmodifiableClassException e)
|
||||
{
|
||||
// Write exception to stdout
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isToBeConsideredForCoverage(String className,
|
||||
ProtectionDomain protectionDomain)
|
||||
{
|
||||
// Don't modify self
|
||||
if (className.startsWith("gb.instrument"))
|
||||
{
|
||||
if (args.isVerboseMode())
|
||||
{
|
||||
System.out.println("Ignoring class in gb.instrument package: " + className);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't modify a class which is already modified
|
||||
if (modifiedClasses.contains(className))
|
||||
{
|
||||
if (args.isVerboseMode())
|
||||
{
|
||||
System.out.println("Ignoring class already modified: " + className);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't modify test classes
|
||||
int p = className.lastIndexOf('$');
|
||||
if (className.endsWith("Test") || p > 0
|
||||
&& className.substring(0, p).endsWith("Test"))
|
||||
{
|
||||
if (args.isVerboseMode())
|
||||
{
|
||||
System.out.println("Ignoring class name ending in Test: " + className);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't modify classes which fail to match the regex
|
||||
if ((args.getClassRegex() == null) ||
|
||||
!args.getClassRegex().matcher(className).matches())
|
||||
{
|
||||
if (args.isVerboseMode())
|
||||
{
|
||||
System.out.println("Ignoring class not matching the active regex: " + className);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't modify a class from a JAR file unless this is allowed
|
||||
CodeSource codeSource = protectionDomain.getCodeSource();
|
||||
if (!args.allowJarsToBeTraced() &&
|
||||
(codeSource != null) &&
|
||||
codeSource.getLocation().getPath().endsWith(".jar"))
|
||||
{
|
||||
if (args.isVerboseMode())
|
||||
{
|
||||
System.out.println("Ignoring class in a JAR: " + className);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(ClassLoader loader,
|
||||
String internalClassName,
|
||||
Class<?> classBeingRedefined,
|
||||
ProtectionDomain protectionDomain,
|
||||
byte[] originalClassfile)
|
||||
throws IllegalClassFormatException
|
||||
{
|
||||
String className = internalClassName.replace('/', '.');
|
||||
if (args.isTracingEnabled() &&
|
||||
isToBeConsideredForCoverage(className, protectionDomain))
|
||||
{
|
||||
if (args.isVerboseMode())
|
||||
{
|
||||
System.out.println("!! Instrumenting class: " + className);
|
||||
}
|
||||
byte[] newBytes = readAndModifyClassForTracing(className, originalClassfile);
|
||||
|
||||
if (args.saveTracedClassfiles())
|
||||
{
|
||||
try
|
||||
{
|
||||
File classOut = new File("./genbin/" + internalClassName + "_gen.class");
|
||||
File parentDir = classOut.getParentFile();
|
||||
boolean dirExists = parentDir.exists();
|
||||
if (!dirExists)
|
||||
{
|
||||
dirExists = parentDir.mkdirs();
|
||||
}
|
||||
if (dirExists)
|
||||
{
|
||||
OutputStream out = new FileOutputStream(classOut);
|
||||
out.write(newBytes);
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("Can't create directory " + parentDir +
|
||||
" for saving traced classfiles.");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
modifiedClasses.add(className);
|
||||
return newBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
modifiedClasses.remove(className);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] readAndModifyClassForTracing(String xiClassName,
|
||||
byte[] classfileBuffer)
|
||||
{
|
||||
ClassReader cr = new ClassReader(classfileBuffer);
|
||||
ClassBranchLineAnalysis analysis = new ClassBranchLineAnalysis();
|
||||
cr.accept(analysis, false);
|
||||
InstrumentedClassWriter writer = new InstrumentedClassWriter(xiClassName,
|
||||
cr,
|
||||
analysis.getMethodBranchLabels());
|
||||
cr.accept(writer, false);
|
||||
return writer.toByteArray();
|
||||
}
|
||||
|
||||
public String getResponse(String message)
|
||||
{
|
||||
AgentSettings oldSettings = new AgentSettings(args);
|
||||
args.parseArgs(message);
|
||||
|
||||
if (args.isVerboseMode() &&
|
||||
(oldSettings.isVerboseMode() != args.isVerboseMode()))
|
||||
{
|
||||
System.out.println(args.toString());
|
||||
}
|
||||
else if (oldSettings.isTracingEnabled() != args.isTracingEnabled())
|
||||
{
|
||||
System.out.println("## Settings Changed");
|
||||
setTracingEnabled(oldSettings.isTracingEnabled());
|
||||
}
|
||||
else if (!oldSettings.getClassRegex().pattern().equals(args.getClassRegex().pattern()))
|
||||
{
|
||||
System.out.println("## Settings Changed");
|
||||
recheckModifiedClasses();
|
||||
traceLoadedClasses();
|
||||
}
|
||||
else if (oldSettings.allowJarsToBeTraced() != args.allowJarsToBeTraced())
|
||||
{
|
||||
System.out.println("## Settings Changed");
|
||||
recheckModifiedClasses();
|
||||
traceLoadedClasses();
|
||||
}
|
||||
else if (oldSettings.saveTracedClassfiles() != args.saveTracedClassfiles())
|
||||
{
|
||||
System.out.println("## Settings Changed");
|
||||
recheckModifiedClasses();
|
||||
traceLoadedClasses();
|
||||
}
|
||||
|
||||
return AgentHelper.getActiveOutputHandler().getResponse(message);
|
||||
}
|
||||
|
||||
public Map<String, String> getSettings()
|
||||
{
|
||||
return args.getSettingsMap();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
* ASM2 ClassWriter used to transform class files to add Trace output.
|
||||
*/
|
||||
public class InstrumentedClassWriter extends ClassWriter
|
||||
{
|
||||
private final String mClassName;
|
||||
private final Map<String, Set<Integer>> methodBranchTraceLines;
|
||||
|
||||
/**
|
||||
* cTor
|
||||
*
|
||||
* @param xiClassName
|
||||
* @param xiReader
|
||||
* @param xiMap
|
||||
*/
|
||||
public InstrumentedClassWriter(String xiClassName, ClassReader xiReader,
|
||||
Map<String, Set<Integer>> xiMap)
|
||||
{
|
||||
super(xiReader, true);
|
||||
mClassName = xiClassName;
|
||||
methodBranchTraceLines = xiMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc,
|
||||
String signature, String[] exceptions)
|
||||
{
|
||||
MethodVisitor mv = super.visitMethod(access, name, desc, signature,
|
||||
exceptions);
|
||||
Set<Integer> branchTraceLines = methodBranchTraceLines.get(name + desc);
|
||||
if (branchTraceLines == null)
|
||||
{
|
||||
branchTraceLines = new HashSet<Integer>();
|
||||
}
|
||||
return new InstrumentedMethodWriter(mv, mClassName, name, desc, branchTraceLines);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
|
||||
import static org.objectweb.asm.Opcodes.RETURN;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodAdapter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
/**
|
||||
* ASM2 MethodVisitor used to add trace to methods.
|
||||
*/
|
||||
public class InstrumentedMethodWriter extends MethodAdapter
|
||||
{
|
||||
private static final String HELPER_CLASS = "gb/instrument/agent/AgentHelper";
|
||||
private final String className;
|
||||
private final String methodName;
|
||||
private final String methodDescriptor;
|
||||
private int lineNumber = -1;
|
||||
|
||||
private final Set<Integer> branchTraceLines;
|
||||
|
||||
private boolean writeTraceLine = false;
|
||||
|
||||
/**
|
||||
* cTor
|
||||
* @param xiMethodVisitor
|
||||
* @param xiClassName
|
||||
* @param xiMethodName
|
||||
* @param xiDesc
|
||||
* @param xiBranchTraceLines
|
||||
*/
|
||||
public InstrumentedMethodWriter(MethodVisitor xiMethodVisitor,
|
||||
String xiClassName,
|
||||
String xiMethodName,
|
||||
String xiDesc,
|
||||
Set<Integer> xiBranchTraceLines)
|
||||
{
|
||||
super(xiMethodVisitor);
|
||||
className = xiClassName;
|
||||
methodName = xiMethodName;
|
||||
methodDescriptor = xiDesc;
|
||||
branchTraceLines = xiBranchTraceLines;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCode()
|
||||
{
|
||||
generateCallToWriteBranchTrace(TraceType.BEGIN,-1);
|
||||
traceArgs();
|
||||
super.visitCode();
|
||||
}
|
||||
|
||||
private void traceArgs()
|
||||
{
|
||||
Type[] argTypes = Type.getArgumentTypes(methodDescriptor);
|
||||
for (int ii = 0; ii < argTypes.length; ii++)
|
||||
{
|
||||
String typeDescriptor = argTypes[ii].getDescriptor();
|
||||
|
||||
if (argTypes[ii].getSort() == Type.OBJECT)
|
||||
{
|
||||
typeDescriptor = "Ljava/lang/Object;";
|
||||
}
|
||||
else if ((argTypes[ii].getSort() == Type.ARRAY) &&
|
||||
(argTypes[ii].getDescriptor().startsWith("[L")))
|
||||
{
|
||||
typeDescriptor = "[Ljava/lang/Object;";
|
||||
}
|
||||
|
||||
mv.visitLdcInsn(className);
|
||||
mv.visitLdcInsn(methodName);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, ii);
|
||||
mv.visitMethodInsn(INVOKESTATIC,
|
||||
HELPER_CLASS,
|
||||
"arg",
|
||||
"(Ljava/lang/String;Ljava/lang/String;" + typeDescriptor + ")V");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumber(int xiLineNumber, Label label)
|
||||
{
|
||||
lineNumber = xiLineNumber;
|
||||
if (writeTraceLine ||
|
||||
branchTraceLines.contains(xiLineNumber))
|
||||
{
|
||||
generateCallToWriteBranchTrace(TraceType.BRANCH, lineNumber);
|
||||
if (writeTraceLine)
|
||||
{
|
||||
writeTraceLine = false;
|
||||
}
|
||||
}
|
||||
super.visitLineNumber(xiLineNumber, label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInsn(int xiOpCode)
|
||||
{
|
||||
if (xiOpCode == RETURN)
|
||||
{
|
||||
generateCallToWriteBranchTrace(TraceType.END, lineNumber);
|
||||
}
|
||||
super.visitInsn(xiOpCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJumpInsn(int xiOpCode, Label xiBranchLabel)
|
||||
{
|
||||
writeTraceLine = true;
|
||||
super.visitJumpInsn(xiOpCode, xiBranchLabel);
|
||||
}
|
||||
|
||||
private void generateCallToWriteBranchTrace(TraceType traceType,
|
||||
int lineNumber)
|
||||
{
|
||||
switch (traceType)
|
||||
{
|
||||
case BEGIN:
|
||||
{
|
||||
mv.visitLdcInsn(className);
|
||||
mv.visitLdcInsn(methodName);
|
||||
mv.visitMethodInsn(INVOKESTATIC,
|
||||
HELPER_CLASS,
|
||||
"enter",
|
||||
"(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
}
|
||||
break;
|
||||
|
||||
case BRANCH:
|
||||
{
|
||||
mv.visitLdcInsn(className);
|
||||
mv.visitLdcInsn(methodName);
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, lineNumber);
|
||||
mv.visitMethodInsn(INVOKESTATIC,
|
||||
HELPER_CLASS,
|
||||
"branch",
|
||||
"(Ljava/lang/String;Ljava/lang/String;I)V");
|
||||
}
|
||||
break;
|
||||
|
||||
case END:
|
||||
{
|
||||
mv.visitLdcInsn(className);
|
||||
mv.visitLdcInsn(methodName);
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, lineNumber);
|
||||
mv.visitMethodInsn(INVOKESTATIC,
|
||||
HELPER_CLASS,
|
||||
"exit",
|
||||
"(Ljava/lang/String;Ljava/lang/String;I)V");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private enum TraceType
|
||||
{
|
||||
BEGIN,
|
||||
BRANCH,
|
||||
END
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package org.intrace.agent.server;
|
||||
|
||||
|
||||
import java.net.BindException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.intrace.agent.ClassTransformer;
|
||||
|
||||
/**
|
||||
* TCP Server used for communication with the Trace client.
|
||||
*/
|
||||
public class AgentServer implements Runnable
|
||||
{
|
||||
private final ClassTransformer transformer;
|
||||
|
||||
/**
|
||||
* cTor
|
||||
* @param xiT
|
||||
*/
|
||||
public AgentServer(ClassTransformer xiT)
|
||||
{
|
||||
transformer= xiT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
int clientNum = 1;
|
||||
int numAllowedExcept = 10;
|
||||
int tracePort = 9123;
|
||||
while (numAllowedExcept > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
ServerSocket serversock = new ServerSocket(tracePort);
|
||||
System.out.println("Listening on port " + serversock.getLocalPort());
|
||||
while (true)
|
||||
{
|
||||
Socket connectedClient = serversock.accept();
|
||||
Thread clientThread = new Thread(new AgentServerConnection(connectedClient, transformer));
|
||||
clientThread.setDaemon(true);
|
||||
clientThread.setName("AgentServer-Client" + clientNum);
|
||||
clientThread.start();
|
||||
clientNum++;
|
||||
}
|
||||
}
|
||||
catch (BindException e)
|
||||
{
|
||||
numAllowedExcept--;
|
||||
System.out.println("Unable to listen on port: " + tracePort);
|
||||
tracePort++;
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
numAllowedExcept--;
|
||||
t.printStackTrace();
|
||||
try
|
||||
{
|
||||
Thread.sleep(5 * 1000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("Too many exceptions - server thread quitting.");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
package org.intrace.agent.server;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.intrace.agent.AgentHelper;
|
||||
import org.intrace.agent.ClassTransformer;
|
||||
|
||||
/**
|
||||
* Server thread handling a single connected client.
|
||||
*/
|
||||
public class AgentServerConnection implements Runnable
|
||||
{
|
||||
private final Socket connectedClient;
|
||||
private final ClassTransformer transformer;
|
||||
|
||||
/**
|
||||
* cTor
|
||||
* @param xiConnectedClient
|
||||
* @param xiTransformer
|
||||
*/
|
||||
public AgentServerConnection(Socket xiConnectedClient,
|
||||
ClassTransformer xiTransformer)
|
||||
{
|
||||
super();
|
||||
connectedClient = xiConnectedClient;
|
||||
transformer = xiTransformer;
|
||||
System.out.println("Connected to: " + xiConnectedClient.getPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
boolean quit = false;
|
||||
while (!quit)
|
||||
{
|
||||
try
|
||||
{
|
||||
String message = receiveMessage(connectedClient);
|
||||
if (message.equals("getsettings"))
|
||||
{
|
||||
Map<String,String> settingsMap = new HashMap<String, String>();
|
||||
settingsMap.putAll(transformer.getSettings());
|
||||
settingsMap.putAll(AgentHelper.getActiveOutputHandler().getSettingsMap());
|
||||
sendMessage(connectedClient, settingsMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
String response = transformer.getResponse(message);
|
||||
if (response != null)
|
||||
{
|
||||
sendMessage(connectedClient, response);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendMessage(connectedClient, "OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
quit = true;
|
||||
}
|
||||
}
|
||||
System.out.println("Disconnected from: " + connectedClient.getPort());
|
||||
connectedClient.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static String receiveMessage(Socket xiConnectedClient) throws IOException
|
||||
{
|
||||
InputStream in = xiConnectedClient.getInputStream();
|
||||
ObjectInputStream objIn = new ObjectInputStream(in);
|
||||
try
|
||||
{
|
||||
return (String)objIn.readObject();
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void sendMessage(Socket xiConnectedClient, Object xiObject) throws IOException
|
||||
{
|
||||
OutputStream out = xiConnectedClient.getOutputStream();
|
||||
ObjectOutputStream objOut = new ObjectOutputStream(out);
|
||||
objOut.writeObject(xiObject);
|
||||
objOut.flush();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
package org.intrace.client.cui;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.tools.attach.VirtualMachine;
|
||||
import com.sun.tools.attach.VirtualMachineDescriptor;
|
||||
|
||||
/**
|
||||
* Command line agent loader.
|
||||
*/
|
||||
public class AgentLoader
|
||||
{
|
||||
/**
|
||||
* Cmd line tool.
|
||||
* @param args
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
BufferedReader readIn = new BufferedReader(new InputStreamReader(System.in));
|
||||
String inLine = "";
|
||||
while (!"quit".equals(inLine))
|
||||
{
|
||||
System.out.print("Enter command [attach/quit]: ");
|
||||
inLine = readIn.readLine();
|
||||
|
||||
if ("attach".equals(inLine))
|
||||
{
|
||||
attachToVM(readIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void attachToVM(BufferedReader xiReadIn)
|
||||
{
|
||||
try
|
||||
{
|
||||
listProcIDs();
|
||||
System.out.print("Choose VM: ");
|
||||
String inLine = xiReadIn.readLine();
|
||||
if (!"".equals(inLine))
|
||||
{
|
||||
VirtualMachine vm = VirtualMachine.attach(inLine);
|
||||
System.out.println("Attached to: " + vm.id());
|
||||
|
||||
while (!"done".equals(inLine))
|
||||
{
|
||||
System.out.print("Enter command [load/done]: ");
|
||||
inLine = xiReadIn.readLine();
|
||||
|
||||
if ("load".equals(inLine))
|
||||
{
|
||||
loadAgent(xiReadIn, vm);
|
||||
}
|
||||
}
|
||||
vm.detach();
|
||||
System.out.println("Detatched from: " + vm.id());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadAgent(BufferedReader xiReadIn, VirtualMachine vm) throws Exception
|
||||
{
|
||||
System.out.print("Enter path to agent jar (blank for windows default): ");
|
||||
String agentPath = xiReadIn.readLine();
|
||||
String defaultAgentPath = "../TestProject/lib/traceagent.jar";
|
||||
if ("".equals(agentPath))
|
||||
{
|
||||
agentPath = defaultAgentPath;
|
||||
}
|
||||
System.out.println("Agent Options");
|
||||
System.out.println("Leave blank for default: [regex-dcl.*");
|
||||
System.out.println("After loading you can only enabled/disable trace");
|
||||
System.out.print("Enter agent options: ");
|
||||
String agentOptions = xiReadIn.readLine();
|
||||
String defaultAgentOpt = "[regex-dcl.*";
|
||||
if ("".equals(agentOptions))
|
||||
{
|
||||
agentOptions = defaultAgentOpt;
|
||||
}
|
||||
vm.loadAgent(agentPath, agentOptions);
|
||||
System.out.println("Loaded agent into: " + vm.toString());
|
||||
}
|
||||
|
||||
private static void listProcIDs()
|
||||
{
|
||||
System.out.println("============== Begin List ==============");
|
||||
List<VirtualMachineDescriptor> vmList = VirtualMachine.list();
|
||||
for (VirtualMachineDescriptor vm : vmList)
|
||||
{
|
||||
System.out.println(vm.displayName() + ":" + vm.id());
|
||||
}
|
||||
System.out.println("============== End List ==============");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package org.intrace.client.cui;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* Command line agent client.
|
||||
*/
|
||||
public class TraceClient
|
||||
{
|
||||
/**
|
||||
* Cmd line tool.
|
||||
* @param args
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
BufferedReader readIn = new BufferedReader(new InputStreamReader(System.in));
|
||||
String inLine = "";
|
||||
while (!"quit".equals(inLine))
|
||||
{
|
||||
System.out.print("Enter command [connect/quit]: ");
|
||||
inLine = readIn.readLine();
|
||||
|
||||
if ("connect".equals(inLine))
|
||||
{
|
||||
connectToAgent(readIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void connectToAgent(BufferedReader xiReadIn) throws Exception
|
||||
{
|
||||
System.out.print("Enter host address: ");
|
||||
String host = xiReadIn.readLine();
|
||||
System.out.print("Enter port: ");
|
||||
String port = xiReadIn.readLine();
|
||||
|
||||
Socket socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(host, Integer.valueOf(port)));
|
||||
|
||||
System.out.println("Connected!");
|
||||
System.out.println("=> " + receiveMessage(socket));
|
||||
|
||||
String inLine = "";
|
||||
while (!"disconnect".equals(inLine))
|
||||
{
|
||||
System.out.print("Enter command [help]: ");
|
||||
inLine = xiReadIn.readLine();
|
||||
if (!"".equals(inLine))
|
||||
{
|
||||
sendMessage(socket, inLine);
|
||||
System.out.println("=> " + receiveMessage(socket));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String receiveMessage(Socket xiConnectedClient) throws IOException
|
||||
{
|
||||
InputStream in = xiConnectedClient.getInputStream();
|
||||
ObjectInputStream objIn = new ObjectInputStream(in);
|
||||
try
|
||||
{
|
||||
return (String)objIn.readObject();
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void sendMessage(Socket xiConnectedClient, String xiString) throws IOException
|
||||
{
|
||||
OutputStream out = xiConnectedClient.getOutputStream();
|
||||
ObjectOutputStream objOut = new ObjectOutputStream(out);
|
||||
objOut.writeObject(xiString);
|
||||
objOut.flush();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
package org.intrace.client.gui;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
public class ConnectionDetails
|
||||
{
|
||||
private final ExecutorService asyncExecutor = Executors.newSingleThreadExecutor(); // @jve:decl-index=0:
|
||||
private Shell sShell = null; // @jve:decl-index=0:visual-constraint="10,10"
|
||||
private Text addressText = null;
|
||||
private Text portText = null;
|
||||
private Label addressLabel = null;
|
||||
private Label portLabel = null;
|
||||
private Button connectButton = null;
|
||||
private Label statusLabel = null;
|
||||
private ConnectionDetails instanceRef = this; // @jve:decl-index=0:
|
||||
|
||||
public void open()
|
||||
{
|
||||
createSShell();
|
||||
sShell.open();
|
||||
Display display = Display.getDefault();
|
||||
while (!sShell.isDisposed())
|
||||
{
|
||||
if (!display.readAndDispatch())
|
||||
display.sleep();
|
||||
}
|
||||
display.dispose();
|
||||
}
|
||||
|
||||
public void show()
|
||||
{
|
||||
sShell.setVisible(true);
|
||||
sShell.setFocus();
|
||||
}
|
||||
|
||||
public void hide()
|
||||
{
|
||||
sShell.setVisible(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method initializes sShell
|
||||
*/
|
||||
private void createSShell()
|
||||
{
|
||||
GridData gridData11 = new GridData();
|
||||
gridData11.horizontalAlignment = org.eclipse.swt.layout.GridData.CENTER;
|
||||
gridData11.widthHint = 400;
|
||||
GridData gridData2 = new GridData();
|
||||
gridData2.widthHint = 400;
|
||||
GridData gridData1 = new GridData();
|
||||
gridData1.widthHint = 400;
|
||||
GridData gridData = new GridData();
|
||||
gridData.grabExcessHorizontalSpace = true;
|
||||
gridData.widthHint = 200;
|
||||
gridData.horizontalAlignment = org.eclipse.swt.layout.GridData.CENTER;
|
||||
GridLayout gridLayout = new GridLayout();
|
||||
gridLayout.numColumns = 2;
|
||||
sShell = new Shell(SWT.CLOSE | SWT.TITLE | SWT.MIN);
|
||||
sShell.setText("Trace Client");
|
||||
sShell.setLayout(gridLayout);
|
||||
sShell.setSize(new Point(475, 126));
|
||||
sShell.addShellListener(new org.eclipse.swt.events.ShellAdapter()
|
||||
{
|
||||
public void shellClosed(org.eclipse.swt.events.ShellEvent e)
|
||||
{
|
||||
asyncExecutor.shutdownNow();
|
||||
sShell.dispose();
|
||||
}
|
||||
});
|
||||
addressLabel = new Label(sShell, SWT.NONE);
|
||||
addressLabel.setText("Address:");
|
||||
addressText = new Text(sShell, SWT.BORDER);
|
||||
addressText.setText("localhost");
|
||||
addressText.setLayoutData(gridData1);
|
||||
portLabel = new Label(sShell, SWT.NONE);
|
||||
portLabel.setText("Port:");
|
||||
portText = new Text(sShell, SWT.BORDER);
|
||||
portText.setText("9123");
|
||||
portText.setLayoutData(gridData2);
|
||||
@SuppressWarnings("unused")
|
||||
Label filler = new Label(sShell, SWT.NONE);
|
||||
connectButton = new Button(sShell, SWT.NONE);
|
||||
connectButton.setText("Connect");
|
||||
connectButton.setLayoutData(gridData);
|
||||
Label filler1 = new Label(sShell, SWT.NONE);
|
||||
filler1.setText("Status:");
|
||||
statusLabel = new Label(sShell, SWT.WRAP | SWT.LEFT);
|
||||
statusLabel.setText("Enter Details Above");
|
||||
statusLabel.setLayoutData(gridData11);
|
||||
connectButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
String host = addressText.getText();
|
||||
String port = portText.getText();
|
||||
connectToAgent(host, port);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void connectToAgent(final String host, final String port)
|
||||
{
|
||||
if (host.length() == 0)
|
||||
{
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
statusLabel.setText("Please enter an address");
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (port.length() == 0)
|
||||
{
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
statusLabel.setText("Please enter a port");
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
statusLabel.setText("Connecting...");
|
||||
asyncExecutor.execute(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
final Socket socket = new Socket();
|
||||
String statusMessage;
|
||||
try
|
||||
{
|
||||
socket.connect(new InetSocketAddress(host, Integer.valueOf(port)));
|
||||
statusMessage = "Connected";
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
hide();
|
||||
TraceWindow traceWindow = new TraceWindow(instanceRef, socket);
|
||||
traceWindow.open();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
statusMessage = e.toString();
|
||||
}
|
||||
final String statusMessageRef = statusMessage;
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
statusLabel.setText(statusMessageRef);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
package org.intrace.client.gui;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.intrace.agent.AgentConfigConstants;
|
||||
import org.intrace.output.trace.TraceConfigConstants;
|
||||
|
||||
public class ParsedSettingsData
|
||||
{
|
||||
public final String classRegex;
|
||||
public final boolean instrEnabled;
|
||||
public final boolean saveTracedClassfiles;
|
||||
public final boolean verboseMode;
|
||||
public final boolean allowJarsToBeTraced;
|
||||
|
||||
public final boolean entryExitEnabled;
|
||||
public final boolean branchEnabled;
|
||||
public final boolean argsEnabled;
|
||||
public final boolean stdOutEnabled;
|
||||
public final boolean fileOutEnabled;
|
||||
public ParsedSettingsData(Map<String, String> settingsMap)
|
||||
{
|
||||
classRegex = settingsMap.get(AgentConfigConstants.CLASS_REGEX);
|
||||
|
||||
if ("true".equals(settingsMap.get(AgentConfigConstants.TRACING_ENABLED)))
|
||||
{
|
||||
instrEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
instrEnabled = false;
|
||||
}
|
||||
|
||||
if ("true".equals(settingsMap.get(AgentConfigConstants.SAVE_TRACED_CLASSFILES)))
|
||||
{
|
||||
saveTracedClassfiles = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
saveTracedClassfiles = false;
|
||||
}
|
||||
|
||||
if ("true".equals(settingsMap.get(AgentConfigConstants.VERBOSE_MODE)))
|
||||
{
|
||||
verboseMode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
verboseMode = false;
|
||||
}
|
||||
|
||||
if ("true".equals(settingsMap.get(AgentConfigConstants.ALLOW_JARS_TO_BE_TRACED)))
|
||||
{
|
||||
allowJarsToBeTraced = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
allowJarsToBeTraced = false;
|
||||
}
|
||||
|
||||
if ("true".equals(settingsMap.get(TraceConfigConstants.ENTRY_EXIT)))
|
||||
{
|
||||
entryExitEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
entryExitEnabled = false;
|
||||
}
|
||||
|
||||
if ("true".equals(settingsMap.get(TraceConfigConstants.BRANCH)))
|
||||
{
|
||||
branchEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
branchEnabled = false;
|
||||
}
|
||||
|
||||
if ("true".equals(settingsMap.get(TraceConfigConstants.ARG)))
|
||||
{
|
||||
argsEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
argsEnabled = false;
|
||||
}
|
||||
|
||||
if ("true".equals(settingsMap.get(TraceConfigConstants.STD_OUT)))
|
||||
{
|
||||
stdOutEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
stdOutEnabled = false;
|
||||
}
|
||||
|
||||
if ("true".equals(settingsMap.get(TraceConfigConstants.FILE_OUT)))
|
||||
{
|
||||
fileOutEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fileOutEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package org.intrace.client.gui;
|
||||
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
public class RegexInput
|
||||
{
|
||||
|
||||
private Shell sShell = null; // @jve:decl-index=0:visual-constraint="10,10"
|
||||
private Text regexInput = null;
|
||||
private Button setRegexButton = null;
|
||||
private Button cancelButton = null;
|
||||
private TraceWindow instanceRef = null; // @jve:decl-index=0:
|
||||
|
||||
/**
|
||||
* This method initializes sShell
|
||||
*/
|
||||
private void createSShell()
|
||||
{
|
||||
GridData gridData2 = new GridData();
|
||||
gridData2.widthHint = 100;
|
||||
gridData2.horizontalAlignment = org.eclipse.swt.layout.GridData.CENTER;
|
||||
GridData gridData1 = new GridData();
|
||||
gridData1.widthHint = 100;
|
||||
gridData1.horizontalAlignment = org.eclipse.swt.layout.GridData.CENTER;
|
||||
GridData gridData = new GridData();
|
||||
gridData.horizontalSpan = 2;
|
||||
gridData.widthHint = 300;
|
||||
GridLayout gridLayout = new GridLayout();
|
||||
gridLayout.numColumns = 2;
|
||||
gridLayout.makeColumnsEqualWidth = true;
|
||||
sShell = new Shell(SWT.APPLICATION_MODAL | SWT.CLOSE | SWT.TITLE | SWT.MIN);
|
||||
sShell.setText("Enter Regex");
|
||||
sShell.setLayout(gridLayout);
|
||||
sShell.setSize(new Point(326, 82));
|
||||
sShell.addShellListener(new org.eclipse.swt.events.ShellAdapter()
|
||||
{
|
||||
public void shellClosed(org.eclipse.swt.events.ShellEvent e)
|
||||
{
|
||||
sShell.dispose();
|
||||
}
|
||||
});
|
||||
regexInput = new Text(sShell, SWT.BORDER);
|
||||
regexInput.setLayoutData(gridData);
|
||||
setRegexButton = new Button(sShell, SWT.NONE);
|
||||
setRegexButton.setText("Set Class Regex");
|
||||
setRegexButton.setLayoutData(gridData1);
|
||||
setRegexButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
instanceRef.setRegex(regexInput.getText());
|
||||
sShell.close();
|
||||
}
|
||||
});
|
||||
cancelButton = new Button(sShell, SWT.NONE);
|
||||
cancelButton.setText("Cancel");
|
||||
cancelButton.setLayoutData(gridData2);
|
||||
cancelButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
sShell.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void open(TraceWindow instanceWindowRef, String initText)
|
||||
{
|
||||
createSShell();
|
||||
sShell.open();
|
||||
regexInput.setText(initText);
|
||||
instanceRef = instanceWindowRef;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package org.intrace.client.gui;
|
||||
|
||||
public class TraceClient
|
||||
{
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
{
|
||||
ConnectionDetails enterConnectionDetails = new ConnectionDetails();
|
||||
enterConnectionDetails.open();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,617 @@
|
|||
package org.intrace.client.gui;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.layout.FillLayout;
|
||||
|
||||
public class TraceWindow
|
||||
{
|
||||
private final String ENABLE_INSTR = "Enable Instrumentation";
|
||||
private final String DISABLE_INSTR = "Disable Instrumentation";
|
||||
|
||||
private final String SET_CLASSREGEX = "Set Class Regex...";
|
||||
|
||||
private final String ENABLE_ALLOWJARS = "Enable JAR Instrumentation";
|
||||
private final String DISABLE_ALLOWJARS = "Disable JAR Instrumentation";
|
||||
|
||||
private final String ENABLE_SAVECLASSES = "Save Instrumented Classes";
|
||||
private final String DISABLE_SAVECLASSES = "Don't Save Classes";
|
||||
|
||||
private final String ENABLE_VERBOSEMODE = "Enable Verbose Mode";
|
||||
private final String DISABLE_VERBOSEMODE = "Disable Verbose Mode";
|
||||
|
||||
private final String ENABLE_EE_TRACE = "Enable Entry/Exit Trace";
|
||||
private final String DISABLE_EE_TRACE = "Disable Entry/Exit Trace";
|
||||
|
||||
private final String ENABLE_BRANCH_TRACE = "Enable Branch Trace";
|
||||
private final String DISABLE_BRANCH_TRACE = "Disable Branch Trace";
|
||||
|
||||
private final String ENABLE_ARGS_TRACE = "Enable Args Trace";
|
||||
private final String DISABLE_ARGS_TRACE = "Disable Args Trace";
|
||||
|
||||
private final String ENABLE_STDOUT_TRACE = "Enable StdOut Trace";
|
||||
private final String DISABLE_STDOUT_TRACE = "Disable StdOut Trace";
|
||||
|
||||
private final String ENABLE_FILE_TRACE = "Enable File Trace";
|
||||
private final String DISABLE_FILE_TRACE = "Disable File Trace";
|
||||
|
||||
private final String ENABLE_NETWORK_TRACE = "Enable Network Trace";
|
||||
private final String DISABLE_NETWORK_TRACE = "Disable Network Trace";
|
||||
|
||||
private ParsedSettingsData settingsData = new ParsedSettingsData(new HashMap<String, String>()); // @jve:decl-index=0:
|
||||
private final ExecutorService asyncExecutor = Executors.newSingleThreadExecutor(); // @jve:decl-index=0:
|
||||
private TraceWindow instanceWindowRef = this;
|
||||
|
||||
private boolean networkTraceEnabled = false;
|
||||
private NetworkTraceThread networkThread;
|
||||
|
||||
private Shell sShell = null;
|
||||
private Button toggleEntryExitButton = null;
|
||||
private Button Disconnect = null;
|
||||
private Text statusTextArea = null;
|
||||
|
||||
private ConnectionDetails instanceRef;
|
||||
private Socket socket;
|
||||
private Button toggleStdOutButton = null;
|
||||
private Button toggleBranchButton = null;
|
||||
private Button toggleArgsButton = null;
|
||||
private Label traceSettingsLabel = null;
|
||||
private Label outputSettingsLabel = null;
|
||||
private Label spacerLabel = null;
|
||||
private Composite composite = null;
|
||||
private Label instrumentSettingsLabel = null;
|
||||
private Button toggleInstrumentEnabled = null;
|
||||
private Button setClassRegexButton = null;
|
||||
private Button toggleAllowJarInstru = null;
|
||||
private Button toggleSaveClassFiles = null;
|
||||
private Button toggleVerboseMode = null;
|
||||
private Button toggleFileOutputButton = null;
|
||||
private Button toggleNetworkTraceButton = null;
|
||||
public TraceWindow(ConnectionDetails instanceRef, Socket socket)
|
||||
{
|
||||
this.instanceRef = instanceRef;
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method initializes sShell
|
||||
*/
|
||||
private void createSShell()
|
||||
{
|
||||
GridData gridData22 = new GridData();
|
||||
gridData22.widthHint = 150;
|
||||
GridData gridData11 = new GridData();
|
||||
gridData11.widthHint = 150;
|
||||
GridData gridData7 = new GridData();
|
||||
gridData7.widthHint = 150;
|
||||
GridData gridData6 = new GridData();
|
||||
gridData6.widthHint = 150;
|
||||
GridData gridData5 = new GridData();
|
||||
gridData5.widthHint = 150;
|
||||
GridData gridData41 = new GridData();
|
||||
gridData41.widthHint = 150;
|
||||
GridData gridData31 = new GridData();
|
||||
gridData31.widthHint = 150;
|
||||
GridData gridData21 = new GridData();
|
||||
gridData21.widthHint = 150;
|
||||
GridData gridData1 = new GridData();
|
||||
gridData1.widthHint = 150;
|
||||
GridData gridData4 = new GridData();
|
||||
gridData4.widthHint = 150;
|
||||
GridLayout gridLayout = new GridLayout();
|
||||
gridLayout.numColumns = 2;
|
||||
GridData gridData2 = new GridData();
|
||||
gridData2.widthHint = 150;
|
||||
GridData gridData = new GridData();
|
||||
gridData.widthHint = 150;
|
||||
gridData.verticalAlignment = org.eclipse.swt.layout.GridData.BEGINNING;
|
||||
sShell = new Shell();
|
||||
sShell.setText("Trace Window");
|
||||
sShell.setLayout(gridLayout);
|
||||
sShell.setSize(new Point(500, 500));
|
||||
instrumentSettingsLabel = new Label(sShell, SWT.NONE);
|
||||
instrumentSettingsLabel.setText("Instrumentation Settings:");
|
||||
createComposite();
|
||||
toggleInstrumentEnabled = new Button(sShell, SWT.LEFT);
|
||||
toggleInstrumentEnabled.setText(ENABLE_INSTR);
|
||||
toggleInstrumentEnabled.setLayoutData(gridData31);
|
||||
toggleInstrumentEnabled
|
||||
.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
toggleSetting(settingsData.instrEnabled, "[instru-true", "[instru-false");
|
||||
}
|
||||
});
|
||||
setClassRegexButton = new Button(sShell, SWT.LEFT);
|
||||
setClassRegexButton.setText(SET_CLASSREGEX);
|
||||
setClassRegexButton.setLayoutData(gridData41);
|
||||
setClassRegexButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
RegexInput regexInput = new RegexInput();
|
||||
regexInput.open(instanceWindowRef, settingsData.classRegex);
|
||||
}
|
||||
});
|
||||
toggleAllowJarInstru = new Button(sShell, SWT.LEFT);
|
||||
toggleAllowJarInstru.setText(ENABLE_ALLOWJARS);
|
||||
toggleAllowJarInstru.setLayoutData(gridData5);
|
||||
toggleAllowJarInstru.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
toggleSetting(settingsData.allowJarsToBeTraced, "[instrujars-true", "[instrujars-false");
|
||||
}
|
||||
});
|
||||
toggleSaveClassFiles = new Button(sShell, SWT.LEFT);
|
||||
toggleSaveClassFiles.setText(ENABLE_SAVECLASSES);
|
||||
toggleSaveClassFiles.setLayoutData(gridData6);
|
||||
toggleSaveClassFiles.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
toggleSetting(settingsData.saveTracedClassfiles, "[saveinstru-true", "[saveinstru-false");
|
||||
}
|
||||
});
|
||||
toggleVerboseMode = new Button(sShell, SWT.LEFT);
|
||||
toggleVerboseMode.setText(ENABLE_VERBOSEMODE);
|
||||
toggleVerboseMode.setLayoutData(gridData7);
|
||||
toggleVerboseMode.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
toggleSetting(settingsData.verboseMode, "[verbose-true", "[verbose-false");
|
||||
}
|
||||
});
|
||||
sShell.setMinimumSize(new Point(500, 500));
|
||||
traceSettingsLabel = new Label(sShell, SWT.NONE);
|
||||
traceSettingsLabel.setText("Trace Settings:");
|
||||
sShell.addShellListener(new org.eclipse.swt.events.ShellAdapter()
|
||||
{
|
||||
public void shellClosed(org.eclipse.swt.events.ShellEvent e)
|
||||
{
|
||||
disconnect();
|
||||
sShell.dispose();
|
||||
asyncExecutor.shutdownNow();
|
||||
}
|
||||
});
|
||||
toggleEntryExitButton = new Button(sShell, SWT.LEFT);
|
||||
toggleEntryExitButton.setText(ENABLE_EE_TRACE);
|
||||
toggleEntryExitButton.setLayoutData(gridData2);
|
||||
toggleEntryExitButton
|
||||
.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
toggleSetting(settingsData.entryExitEnabled, "[trace-ee-true", "[trace-ee-false");
|
||||
}
|
||||
});
|
||||
toggleBranchButton = new Button(sShell, SWT.LEFT);
|
||||
toggleBranchButton.setText(ENABLE_BRANCH_TRACE);
|
||||
toggleBranchButton.setLayoutData(gridData1);
|
||||
toggleBranchButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
toggleSetting(settingsData.branchEnabled, "[trace-branch-true", "[trace-branch-false");
|
||||
}
|
||||
});
|
||||
toggleArgsButton = new Button(sShell, SWT.LEFT);
|
||||
toggleArgsButton.setText(ENABLE_ARGS_TRACE);
|
||||
toggleArgsButton.setLayoutData(gridData21);
|
||||
outputSettingsLabel = new Label(sShell, SWT.NONE);
|
||||
outputSettingsLabel.setText("Output Modes:");
|
||||
toggleArgsButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
toggleSetting(settingsData.argsEnabled, "[trace-args-true", "[trace-args-false");
|
||||
}
|
||||
});
|
||||
toggleStdOutButton = new Button(sShell, SWT.LEFT);
|
||||
toggleStdOutButton.setText(ENABLE_STDOUT_TRACE);
|
||||
toggleStdOutButton.setLayoutData(gridData4);
|
||||
toggleFileOutputButton = new Button(sShell, SWT.LEFT);
|
||||
toggleFileOutputButton.setText(ENABLE_FILE_TRACE);
|
||||
toggleFileOutputButton.setLayoutData(gridData11);
|
||||
toggleNetworkTraceButton = new Button(sShell, SWT.LEFT);
|
||||
toggleNetworkTraceButton.setText(ENABLE_NETWORK_TRACE);
|
||||
toggleNetworkTraceButton.setLayoutData(gridData22);
|
||||
toggleNetworkTraceButton
|
||||
.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
toggleNetworkTrace();
|
||||
}
|
||||
});
|
||||
toggleFileOutputButton
|
||||
.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
toggleSetting(settingsData.fileOutEnabled, "[trace-file-true", "[trace-file-false");
|
||||
}
|
||||
});
|
||||
spacerLabel = new Label(sShell, SWT.NONE);
|
||||
spacerLabel.setText("");
|
||||
toggleStdOutButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
toggleSetting(settingsData.stdOutEnabled, "[trace-stdout-true", "[trace-stdout-false");
|
||||
}
|
||||
});
|
||||
Disconnect = new Button(sShell, SWT.LEFT);
|
||||
Disconnect.setText("Disconnect");
|
||||
Disconnect.setLayoutData(gridData);
|
||||
Disconnect.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
|
||||
{
|
||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
|
||||
{
|
||||
sShell.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method initializes composite
|
||||
*
|
||||
*/
|
||||
private void createComposite()
|
||||
{
|
||||
FillLayout fillLayout = new FillLayout();
|
||||
fillLayout.type = org.eclipse.swt.SWT.HORIZONTAL;
|
||||
GridData gridData3 = new GridData();
|
||||
gridData3.grabExcessVerticalSpace = true;
|
||||
gridData3.heightHint = 99999;
|
||||
gridData3.widthHint = 99999;
|
||||
gridData3.verticalSpan = 17;
|
||||
gridData3.grabExcessHorizontalSpace = true;
|
||||
composite = new Composite(sShell, SWT.NONE);
|
||||
composite.setLayoutData(gridData3);
|
||||
composite.setLayout(fillLayout);
|
||||
statusTextArea = new Text(composite, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER);
|
||||
statusTextArea.setEditable(false);
|
||||
statusTextArea.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
|
||||
}
|
||||
|
||||
public void open()
|
||||
{
|
||||
createSShell();
|
||||
sShell.open();
|
||||
statusTextArea.append("Connected!\n");
|
||||
getSettings();
|
||||
}
|
||||
|
||||
private void toggleNetworkTrace()
|
||||
{
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
disableButtons();
|
||||
asyncExecutor.execute(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!networkTraceEnabled)
|
||||
{
|
||||
sendMessage("[trace-network");
|
||||
String networkTracePortStr = (String)receiveMessage();
|
||||
int networkTracePort = Integer.parseInt(networkTracePortStr);
|
||||
networkThread = new NetworkTraceThread(networkTracePort);
|
||||
networkThread.start();
|
||||
networkTraceEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
networkThread.stop();
|
||||
networkTraceEnabled = false;
|
||||
}
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
updateButtonText();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
sShell.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setRegex(final String regex)
|
||||
{
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
disableButtons();
|
||||
asyncExecutor.execute(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
sendMessage("[regex-" + regex);
|
||||
receiveMessage(); // Throw away result message
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
getSettings();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
sShell.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void getSettings()
|
||||
{
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
statusTextArea.append("Fetching Settings...\n");
|
||||
}
|
||||
});
|
||||
asyncExecutor.execute(new Runnable()
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
sendMessage("getsettings");
|
||||
Object receivedMsg = receiveMessage();
|
||||
if (receivedMsg instanceof Map)
|
||||
{
|
||||
Map<String,String> settingsMap = (Map<String,String>)receivedMsg;
|
||||
settingsData = new ParsedSettingsData(settingsMap);
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
updateButtonText();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
sShell.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void toggleSetting(final boolean settingValue, final String enableCommand, final String disableCommand)
|
||||
{
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
disableButtons();
|
||||
asyncExecutor.execute(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (settingValue)
|
||||
{
|
||||
sendMessage(disableCommand);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendMessage(enableCommand);
|
||||
}
|
||||
receiveMessage(); // Throw away result message
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
getSettings();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
sShell.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void disableButtons()
|
||||
{
|
||||
toggleInstrumentEnabled.setEnabled(false);
|
||||
setClassRegexButton.setEnabled(false);
|
||||
toggleAllowJarInstru.setEnabled(false);
|
||||
toggleSaveClassFiles.setEnabled(false);
|
||||
toggleVerboseMode.setEnabled(false);
|
||||
toggleEntryExitButton.setEnabled(false);
|
||||
toggleBranchButton.setEnabled(false);
|
||||
toggleArgsButton.setEnabled(false);
|
||||
toggleStdOutButton.setEnabled(false);
|
||||
toggleFileOutputButton.setEnabled(false);
|
||||
toggleNetworkTraceButton.setEnabled(false);
|
||||
}
|
||||
|
||||
private void chooseText(Button control, boolean option, String enabledText, String disabledText)
|
||||
{
|
||||
if (option)
|
||||
{
|
||||
control.setText(disabledText);
|
||||
}
|
||||
else
|
||||
{
|
||||
control.setText(enabledText);
|
||||
}
|
||||
control.setEnabled(true);
|
||||
}
|
||||
|
||||
private void updateButtonText()
|
||||
{
|
||||
statusTextArea.append("Got Settings...\n");
|
||||
|
||||
chooseText(toggleInstrumentEnabled, settingsData.instrEnabled, ENABLE_INSTR, DISABLE_INSTR);
|
||||
chooseText(toggleAllowJarInstru, settingsData.allowJarsToBeTraced, ENABLE_ALLOWJARS, DISABLE_ALLOWJARS);
|
||||
chooseText(toggleSaveClassFiles, settingsData.saveTracedClassfiles, ENABLE_SAVECLASSES, DISABLE_SAVECLASSES);
|
||||
chooseText(toggleVerboseMode, settingsData.verboseMode, ENABLE_VERBOSEMODE, DISABLE_VERBOSEMODE);
|
||||
chooseText(toggleEntryExitButton, settingsData.entryExitEnabled, ENABLE_EE_TRACE, DISABLE_EE_TRACE);
|
||||
chooseText(toggleBranchButton, settingsData.branchEnabled, ENABLE_BRANCH_TRACE, DISABLE_BRANCH_TRACE);
|
||||
chooseText(toggleArgsButton, settingsData.argsEnabled, ENABLE_ARGS_TRACE, DISABLE_ARGS_TRACE);
|
||||
chooseText(toggleStdOutButton, settingsData.stdOutEnabled, ENABLE_STDOUT_TRACE, DISABLE_STDOUT_TRACE);
|
||||
chooseText(toggleFileOutputButton, settingsData.fileOutEnabled, ENABLE_FILE_TRACE, DISABLE_FILE_TRACE);
|
||||
chooseText(toggleNetworkTraceButton, networkTraceEnabled, ENABLE_NETWORK_TRACE, DISABLE_NETWORK_TRACE);
|
||||
setClassRegexButton.setEnabled(true);
|
||||
}
|
||||
|
||||
private void disconnect()
|
||||
{
|
||||
if (socket.isConnected())
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
instanceRef.show();
|
||||
}
|
||||
}
|
||||
|
||||
private Object receiveMessage() throws IOException
|
||||
{
|
||||
InputStream in = socket.getInputStream();
|
||||
ObjectInputStream objIn = new ObjectInputStream(in);
|
||||
try
|
||||
{
|
||||
return (Object)objIn.readObject();
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void sendMessage(String xiString) throws IOException
|
||||
{
|
||||
OutputStream out = socket.getOutputStream();
|
||||
ObjectOutputStream objOut = new ObjectOutputStream(out);
|
||||
objOut.writeObject(xiString);
|
||||
objOut.flush();
|
||||
}
|
||||
|
||||
private class NetworkTraceThread implements Runnable
|
||||
{
|
||||
private final Socket traceSocket;
|
||||
public NetworkTraceThread(int networkTracePort) throws IOException
|
||||
{
|
||||
traceSocket = new Socket();
|
||||
traceSocket.connect(new InetSocketAddress(socket.getInetAddress(), networkTracePort));
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
Thread t = new Thread(this);
|
||||
t.setDaemon(true);
|
||||
t.setName("Network Trace");
|
||||
t.start();
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
traceSocket.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
ObjectInputStream objIn = new ObjectInputStream(traceSocket.getInputStream());
|
||||
while (true)
|
||||
{
|
||||
final String traceLine = (String)objIn.readObject();
|
||||
sShell.getDisplay().asyncExec(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
statusTextArea.append(traceLine + "\n");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package org.intrace.output;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Output generated by the instrumentation
|
||||
*/
|
||||
public interface IOutput
|
||||
{
|
||||
public void enter(String className, String methodName);
|
||||
|
||||
public void arg(String className, String methodName, byte byteArg);
|
||||
public void arg(String className, String methodName, byte[] byteArrayArg);
|
||||
public void arg(String className, String methodName, short shortArg);
|
||||
public void arg(String className, String methodName, short[] shortArrayArg);
|
||||
|
||||
public void arg(String className, String methodName, int intArg);
|
||||
public void arg(String className, String methodName, int[] intArrayArg);
|
||||
public void arg(String className, String methodName, long longArg);
|
||||
public void arg(String className, String methodName, long[] longArrayArg);
|
||||
|
||||
public void arg(String className, String methodName, float floatArg);
|
||||
public void arg(String className, String methodName, float[] floatArrayArg);
|
||||
public void arg(String className, String methodName, double doubleArg);
|
||||
public void arg(String className, String methodName, double[] doubleArrayArg);
|
||||
|
||||
public void arg(String className, String methodName, boolean boolArg);
|
||||
public void arg(String className, String methodName, boolean[] boolArrayArg);
|
||||
public void arg(String className, String methodName, char charArg);
|
||||
public void arg(String className, String methodName, char[] charArrayArg);
|
||||
|
||||
public void arg(String className, String methodName, Object objArg);
|
||||
public void arg(String className, String methodName, Object[] objArrayArg);
|
||||
|
||||
public void branch(String className, String methodName, int lineNo);
|
||||
public void exit(String className, String methodName, int lineNo);
|
||||
|
||||
public String getResponse(String args);
|
||||
public Map<String,String> getSettingsMap();
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package org.intrace.output.trace;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class NetworkTraceThread implements Runnable
|
||||
{
|
||||
private final ServerSocket networkSocket;
|
||||
private final BlockingQueue<String> outgoingTrace = new LinkedBlockingQueue<String>(100);
|
||||
private Set<NetworkTraceThread> set;
|
||||
|
||||
public NetworkTraceThread(ServerSocket networkSocket)
|
||||
{
|
||||
this.networkSocket = networkSocket;
|
||||
}
|
||||
|
||||
public void start(Set<NetworkTraceThread> set)
|
||||
{
|
||||
this.set = set;
|
||||
|
||||
Thread networkThread = new Thread(this);
|
||||
networkThread.setDaemon(true);
|
||||
networkThread.setName("Network-Trace");
|
||||
networkThread.start();
|
||||
}
|
||||
|
||||
private void stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
networkSocket.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
set.remove(this);
|
||||
System.out.println("## Network Trace Disconnected");
|
||||
}
|
||||
|
||||
public void queueTrace(String traceLine)
|
||||
{
|
||||
try
|
||||
{
|
||||
outgoingTrace.put(traceLine);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Socket traceSendingSocket;
|
||||
try
|
||||
{
|
||||
traceSendingSocket = networkSocket.accept();
|
||||
try
|
||||
{
|
||||
ObjectOutputStream traceWriter = new ObjectOutputStream(traceSendingSocket.getOutputStream());
|
||||
while (true)
|
||||
{
|
||||
String traceLine = outgoingTrace.take();
|
||||
traceWriter.writeObject(traceLine);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
traceSendingSocket.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
catch (Exception e1)
|
||||
{
|
||||
stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package org.intrace.output.trace;
|
||||
|
||||
public class TraceConfigConstants
|
||||
{
|
||||
public static final String ENTRY_EXIT = "TRACE_ENTRY_EXIT";
|
||||
public static final String BRANCH = "TRACE_BRANCH";
|
||||
public static final String ARG = "TRACE_ARG";
|
||||
public static final String STD_OUT = "TRACE_STD_OUT";
|
||||
public static final String FILE_OUT = "TRACE_FILE_OUT";
|
||||
}
|
||||
|
|
@ -0,0 +1,336 @@
|
|||
package org.intrace.output.trace;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.intrace.output.IOutput;
|
||||
|
||||
/**
|
||||
* Implements Standard Output Tracing
|
||||
*/
|
||||
public class TraceOutput implements IOutput
|
||||
{
|
||||
private boolean entryExitTrace = true;
|
||||
private boolean branchTrace = false;
|
||||
private boolean argTrace = false;
|
||||
|
||||
private boolean stdoutTrace = true;
|
||||
private boolean fileoutTrace = false;
|
||||
private boolean file1Active = true;
|
||||
private int writtenChars = 0;
|
||||
private final int MAX_CHARS_PER_FILE = 100 * 1000; // 100kb
|
||||
|
||||
final TraceSettings traceSettings = new TraceSettings("");
|
||||
|
||||
private Map<NetworkTraceThread,Object> traceThreads = new ConcurrentHashMap<NetworkTraceThread,Object>();
|
||||
|
||||
public String getResponse(String args)
|
||||
{
|
||||
TraceSettings oldSettings = new TraceSettings(traceSettings);
|
||||
traceSettings.parseArgs(args);
|
||||
|
||||
if ((oldSettings.isEntryExitTraceEnabled() != traceSettings.isEntryExitTraceEnabled()) ||
|
||||
(oldSettings.isBranchTraceEnabled() != traceSettings.isBranchTraceEnabled()) ||
|
||||
(oldSettings.isArgTraceEnabled() != traceSettings.isArgTraceEnabled()) ||
|
||||
(oldSettings.isStdoutTraceOutputEnabled() != traceSettings.isStdoutTraceOutputEnabled()) ||
|
||||
(oldSettings.isFileTraceOutputEnabled() != traceSettings.isFileTraceOutputEnabled()))
|
||||
{
|
||||
System.out.println("## Trace Settings Changed");
|
||||
}
|
||||
|
||||
entryExitTrace = traceSettings.isEntryExitTraceEnabled();
|
||||
branchTrace = traceSettings.isBranchTraceEnabled();
|
||||
argTrace = traceSettings.isArgTraceEnabled();
|
||||
stdoutTrace = traceSettings.isStdoutTraceOutputEnabled();
|
||||
fileoutTrace = traceSettings.isFileTraceOutputEnabled();
|
||||
|
||||
if (traceSettings.networkTraceOutputRequested)
|
||||
{
|
||||
System.out.println("## Network Trace Requested");
|
||||
ServerSocket networkSocket;
|
||||
try
|
||||
{
|
||||
networkSocket = new ServerSocket(0);
|
||||
NetworkTraceThread traceThread = new NetworkTraceThread(networkSocket);
|
||||
|
||||
traceThreads.put(traceThread, new Object());
|
||||
|
||||
traceThread.start(traceThreads.keySet());
|
||||
traceSettings.networkTraceOutputRequested = false;
|
||||
return Integer.toString(networkSocket.getLocalPort());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Do nothing
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String,String> getSettingsMap()
|
||||
{
|
||||
return traceSettings.getSettingsMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write trace output
|
||||
*
|
||||
* @param xiTrace
|
||||
*/
|
||||
private void writeTrace(String xiTrace)
|
||||
{
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat();
|
||||
long threadID = Thread.currentThread().getId();
|
||||
String traceString = "[" + dateFormat.format(new Date()) + "]:[" +
|
||||
threadID + "]:" + xiTrace;
|
||||
if (stdoutTrace)
|
||||
{
|
||||
System.out.println(traceString);
|
||||
}
|
||||
|
||||
if (fileoutTrace)
|
||||
{
|
||||
writeFileTrace(traceString);
|
||||
}
|
||||
|
||||
Set<NetworkTraceThread> networkThreads = traceThreads.keySet();
|
||||
if (networkThreads.size() > 0)
|
||||
{
|
||||
for (NetworkTraceThread thread : networkThreads)
|
||||
{
|
||||
thread.queueTrace(traceString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void writeFileTrace(String traceString)
|
||||
{
|
||||
PrintWriter outputWriter;
|
||||
if (file1Active)
|
||||
{
|
||||
outputWriter = traceSettings.getFile1TraceWriter();
|
||||
}
|
||||
else
|
||||
{
|
||||
outputWriter = traceSettings.getFile2TraceWriter();
|
||||
}
|
||||
outputWriter.println(traceString);
|
||||
outputWriter.flush();
|
||||
|
||||
// Switch trace files if necessary
|
||||
writtenChars += traceString.length();
|
||||
if (writtenChars > MAX_CHARS_PER_FILE)
|
||||
{
|
||||
writtenChars = 0;
|
||||
traceSettings.resetTraceFiles(file1Active, !file1Active);
|
||||
file1Active = !file1Active;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, byte byteArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: " + byteArg);
|
||||
}
|
||||
}
|
||||
|
||||
public void arg(String className, String methodName, byte[] byteArrayArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: "
|
||||
+ Arrays.toString(byteArrayArg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, short shortArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: " + shortArg);
|
||||
}
|
||||
}
|
||||
|
||||
public void arg(String className, String methodName, short[] shortArrayArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: "
|
||||
+ Arrays.toString(shortArrayArg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, int intArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: " + intArg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, int[] intArrayArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: "
|
||||
+ Arrays.toString(intArrayArg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, long longArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: " + longArg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, long[] longArrayArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: "
|
||||
+ Arrays.toString(longArrayArg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, float floatArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: " + floatArg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, float[] floatArrayArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: "
|
||||
+ Arrays.toString(floatArrayArg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, double doubleArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: " + doubleArg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, double[] doubleArrayArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: "
|
||||
+ Arrays.toString(doubleArrayArg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, boolean boolArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: " + boolArg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, boolean[] boolArrayArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: "
|
||||
+ Arrays.toString(boolArrayArg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, char charArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: " + charArg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, char[] charArrayArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: "
|
||||
+ Arrays.toString(charArrayArg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arg(String className, String methodName, Object objArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: " + objArg);
|
||||
}
|
||||
}
|
||||
|
||||
public void arg(String className, String methodName, Object[] objArrayArg)
|
||||
{
|
||||
if (argTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": Arg: "
|
||||
+ Arrays.toString(objArrayArg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void branch(String className, String methodName, int lineNo)
|
||||
{
|
||||
if (branchTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": /:" + lineNo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enter(String className, String methodName)
|
||||
{
|
||||
if (entryExitTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": {");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exit(String className, String methodName, int lineNo)
|
||||
{
|
||||
if (entryExitTrace)
|
||||
{
|
||||
writeTrace(className + ":" + methodName + ": }:" + lineNo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
package org.intrace.output.trace;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Args Format:
|
||||
* "[arg1[arg2[arg3"
|
||||
*
|
||||
* where argx is of the form
|
||||
* value-parameter
|
||||
*/
|
||||
public class TraceSettings
|
||||
{
|
||||
private boolean entryExitTraceEnabled = true;
|
||||
private boolean branchTraceEnabled = false;
|
||||
private boolean argTraceEnabled = false;
|
||||
|
||||
private boolean stdoutTraceOutputEnabled = true;
|
||||
private boolean fileTraceOutputEnabled = false;
|
||||
private File file1;
|
||||
private File file2;
|
||||
private PrintWriter file1TraceWriter;
|
||||
private PrintWriter file2TraceWriter;
|
||||
|
||||
public boolean networkTraceOutputRequested = false;
|
||||
|
||||
public TraceSettings(TraceSettings oldSettings)
|
||||
{
|
||||
entryExitTraceEnabled = oldSettings.entryExitTraceEnabled;
|
||||
branchTraceEnabled = oldSettings.branchTraceEnabled;
|
||||
argTraceEnabled = oldSettings.argTraceEnabled;
|
||||
|
||||
stdoutTraceOutputEnabled = oldSettings.stdoutTraceOutputEnabled;
|
||||
fileTraceOutputEnabled = oldSettings.fileTraceOutputEnabled;
|
||||
}
|
||||
|
||||
public TraceSettings(String args)
|
||||
{
|
||||
file1 = new File("trc1.txt");
|
||||
file2 = new File("trc2.txt");
|
||||
resetTraceFiles(true, true);
|
||||
parseArgs(args);
|
||||
}
|
||||
|
||||
public void parseArgs(String args)
|
||||
{
|
||||
String[] seperateArgs = args.split("\\[");
|
||||
for (int ii = 0; ii < seperateArgs.length; ii++)
|
||||
{
|
||||
parseArg(seperateArgs[ii].toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
private void parseArg(String arg)
|
||||
{
|
||||
if (arg.equals("trace-ee-false"))
|
||||
{
|
||||
entryExitTraceEnabled = false;
|
||||
}
|
||||
else if (arg.equals("trace-ee-true"))
|
||||
{
|
||||
entryExitTraceEnabled = true;
|
||||
}
|
||||
else if (arg.equals("trace-branch-true"))
|
||||
{
|
||||
branchTraceEnabled = true;
|
||||
}
|
||||
else if (arg.equals("trace-branch-false"))
|
||||
{
|
||||
branchTraceEnabled = false;
|
||||
}
|
||||
else if (arg.equals("trace-args-true"))
|
||||
{
|
||||
argTraceEnabled = true;
|
||||
}
|
||||
else if (arg.equals("trace-args-false"))
|
||||
{
|
||||
argTraceEnabled = false;
|
||||
}
|
||||
else if (arg.equals("trace-stdout-true"))
|
||||
{
|
||||
stdoutTraceOutputEnabled = true;
|
||||
}
|
||||
else if (arg.equals("trace-stdout-false"))
|
||||
{
|
||||
stdoutTraceOutputEnabled = false;
|
||||
}
|
||||
else if (arg.equals("trace-file-true"))
|
||||
{
|
||||
fileTraceOutputEnabled = true;
|
||||
}
|
||||
else if (arg.equals("trace-file-false"))
|
||||
{
|
||||
fileTraceOutputEnabled = false;
|
||||
}
|
||||
else if (arg.startsWith("trace-file1-"))
|
||||
{
|
||||
String file1Name = arg.replace("trace-file1-", "");
|
||||
file1 = new File(file1Name);
|
||||
resetTraceFiles(true, false);
|
||||
}
|
||||
else if (arg.startsWith("trace-file2-"))
|
||||
{
|
||||
String file2Name = arg.replace("trace-file2-", "");
|
||||
file2 = new File(file2Name);
|
||||
resetTraceFiles(false, true);
|
||||
}
|
||||
else if (arg.equals("trace-network"))
|
||||
{
|
||||
networkTraceOutputRequested = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void resetTraceFiles(boolean resetFile1, boolean resetFile2)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (resetFile1)
|
||||
{
|
||||
file1.delete();
|
||||
file1TraceWriter = new PrintWriter(new FileWriter(file1));
|
||||
}
|
||||
if (resetFile2)
|
||||
{
|
||||
file2.delete();
|
||||
file2TraceWriter = new PrintWriter(new FileWriter(file2));
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEntryExitTraceEnabled()
|
||||
{
|
||||
return entryExitTraceEnabled;
|
||||
}
|
||||
|
||||
public boolean isBranchTraceEnabled()
|
||||
{
|
||||
return branchTraceEnabled;
|
||||
}
|
||||
|
||||
public boolean isArgTraceEnabled()
|
||||
{
|
||||
return argTraceEnabled;
|
||||
}
|
||||
|
||||
public boolean isStdoutTraceOutputEnabled()
|
||||
{
|
||||
return stdoutTraceOutputEnabled;
|
||||
}
|
||||
|
||||
public boolean isFileTraceOutputEnabled()
|
||||
{
|
||||
return fileTraceOutputEnabled;
|
||||
}
|
||||
|
||||
public PrintWriter getFile1TraceWriter()
|
||||
{
|
||||
return file1TraceWriter;
|
||||
}
|
||||
|
||||
public PrintWriter getFile2TraceWriter()
|
||||
{
|
||||
return file2TraceWriter;
|
||||
}
|
||||
|
||||
public Map<String,String> getSettingsMap()
|
||||
{
|
||||
Map<String,String> settingsMap = new HashMap<String, String>();
|
||||
settingsMap.put(TraceConfigConstants.ENTRY_EXIT, Boolean.toString(entryExitTraceEnabled));
|
||||
settingsMap.put(TraceConfigConstants.BRANCH, Boolean.toString(branchTraceEnabled));
|
||||
settingsMap.put(TraceConfigConstants.ARG, Boolean.toString(argTraceEnabled));
|
||||
settingsMap.put(TraceConfigConstants.STD_OUT, Boolean.toString(stdoutTraceOutputEnabled));
|
||||
settingsMap.put(TraceConfigConstants.FILE_OUT, Boolean.toString(fileTraceOutputEnabled));
|
||||
return settingsMap;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue