mirror of https://github.com/mchr3k/org.intrace
commit
831929f4dd
|
|
@ -395,7 +395,7 @@
|
|||
|
||||
<target name="example_build">
|
||||
<mkdir dir="./build/test" />
|
||||
<javac destdir="./build/test" debug="true" source="1.6" target="1.6"
|
||||
<javac destdir="./build/test" debug="true" source="1.7" target="1.7"
|
||||
includeantruntime="false">
|
||||
<src path="./testsrc"/>
|
||||
<classpath>
|
||||
|
|
@ -415,6 +415,16 @@
|
|||
</java>
|
||||
</target>
|
||||
|
||||
<target name="example2" depends="jar,example_build">
|
||||
<java classname="org.intracetest.agent.ArgumentTypes" fork="true">
|
||||
<classpath>
|
||||
<pathelement path="./build/test" />
|
||||
</classpath>
|
||||
<jvmarg value="-javaagent:build/jars/intrace-agent.jar=[instru-true" />
|
||||
</java>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="waitexample" depends="jar,example_build">
|
||||
<java classname="example.TraceExample" fork="true">
|
||||
<arg value="5000" />
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -5,6 +5,7 @@ import java.util.HashMap;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.intrace.output.trace.TraceHandler;
|
||||
import org.intrace.shared.AgentConfigConstants;
|
||||
|
||||
/**
|
||||
|
|
@ -12,9 +13,11 @@ import org.intrace.shared.AgentConfigConstants;
|
|||
*
|
||||
* where argx is of the form value-parameter
|
||||
*/
|
||||
public class AgentSettings
|
||||
public class AgentSettings implements VerboseLogger
|
||||
{
|
||||
// Static settings which control agent startup
|
||||
|
||||
|
||||
// Static settings which control agent startup
|
||||
private int serverPort = 9123;
|
||||
private int callbackPort = -1;
|
||||
private boolean waitStart = false;
|
||||
|
|
@ -23,27 +26,39 @@ public class AgentSettings
|
|||
private int actualServerPort = -1;
|
||||
|
||||
// Dynamic settings
|
||||
private String[] classRegex = new String[0];
|
||||
private String[] excludeClassRegex = new String[0];
|
||||
private InstrCriteria classesToInclude = null;
|
||||
public InstrCriteria getClassesToInclude() {
|
||||
return classesToInclude;
|
||||
}
|
||||
|
||||
|
||||
public InstrCriteria getClassesToExclude() {
|
||||
return classesToExclude;
|
||||
}
|
||||
|
||||
private InstrCriteria classesToExclude = null;
|
||||
private boolean instruEnabled = true;
|
||||
private boolean saveTracedClassfiles = false;
|
||||
private boolean verboseMode = false;
|
||||
|
||||
public AgentSettings(String args)
|
||||
{
|
||||
parseArgs(args);
|
||||
}
|
||||
|
||||
|
||||
public AgentSettings(AgentSettings oldInstance)
|
||||
{
|
||||
// Copy all static state and dynamic settings
|
||||
actualServerPort = oldInstance.getActualServerPort();
|
||||
classRegex = oldInstance.getClassRegex();
|
||||
excludeClassRegex = oldInstance.getExcludeClassRegex();
|
||||
this.classesToInclude = oldInstance.classesToInclude;
|
||||
this.classesToExclude = oldInstance.classesToExclude;
|
||||
|
||||
|
||||
instruEnabled = oldInstance.isInstrumentationEnabled();
|
||||
saveTracedClassfiles = oldInstance.saveTracedClassfiles();
|
||||
verboseMode = oldInstance.isVerboseMode();
|
||||
}
|
||||
public AgentSettings(String args)
|
||||
{
|
||||
parseArgs(args);
|
||||
}
|
||||
|
||||
|
||||
public void parseArgs(String args)
|
||||
|
|
@ -111,7 +126,8 @@ public void parseArgs(String args)
|
|||
else if (arg.startsWith(AgentConfigConstants.CLASS_REGEX))
|
||||
{
|
||||
String classRegexStr = arg.replace(AgentConfigConstants.CLASS_REGEX, "");
|
||||
classRegex = classRegexStr.split("\\|");
|
||||
this.classesToInclude = new InstrCriteria(classRegexStr);
|
||||
this.classesToInclude.verboseLogger = this;
|
||||
}
|
||||
else if (arg.startsWith(AgentConfigConstants.EXCLUDE_CLASS_REGEX))
|
||||
{
|
||||
|
|
@ -119,7 +135,8 @@ public void parseArgs(String args)
|
|||
.replace(
|
||||
AgentConfigConstants.EXCLUDE_CLASS_REGEX,
|
||||
"");
|
||||
excludeClassRegex = classExcludeRegexStr.split("\\|");
|
||||
this.classesToExclude = new InstrCriteria(classExcludeRegexStr);
|
||||
this.classesToExclude.verboseLogger = this;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -150,12 +167,18 @@ public void parseArgs(String args)
|
|||
|
||||
public String[] getClassRegex()
|
||||
{
|
||||
return classRegex;
|
||||
String[] rc = {};
|
||||
if (this.classesToInclude!=null)
|
||||
rc = this.classesToInclude.getClassRegex();
|
||||
return rc;
|
||||
}
|
||||
|
||||
public String[] getExcludeClassRegex()
|
||||
{
|
||||
return excludeClassRegex;
|
||||
String[] rc = {};
|
||||
if (this.classesToExclude!=null)
|
||||
rc = this.classesToInclude.getClassRegex();
|
||||
return rc;
|
||||
}
|
||||
|
||||
public boolean isInstrumentationEnabled()
|
||||
|
|
@ -178,8 +201,17 @@ public void parseArgs(String args)
|
|||
{
|
||||
// Output key settings
|
||||
String currentSettings = "";
|
||||
currentSettings += "Class Regex : " + Arrays.toString(classRegex) + "\n";
|
||||
currentSettings += "Exclude Class Regex : " + Arrays.toString(excludeClassRegex) + "\n";
|
||||
|
||||
String includeString = "";
|
||||
if (this.classesToInclude != null)
|
||||
includeString = this.classesToInclude.toString();
|
||||
currentSettings += "Include Class Regex : " + includeString + "\n";
|
||||
|
||||
String excludeString = "";
|
||||
if (this.classesToExclude != null)
|
||||
excludeString = this.classesToExclude.toString();
|
||||
currentSettings += "Exclude Class Regex : " + excludeString + "\n";
|
||||
|
||||
currentSettings += "Tracing Enabled : " + instruEnabled + "\n";
|
||||
currentSettings += "Save Traced Class Files : " + saveTracedClassfiles
|
||||
+ "\n";
|
||||
|
|
@ -191,10 +223,20 @@ public void parseArgs(String args)
|
|||
Map<String, String> settingsMap = new HashMap<String, String>();
|
||||
settingsMap.put(AgentConfigConstants.INSTRU_ENABLED,
|
||||
Boolean.toString(instruEnabled));
|
||||
|
||||
String includeSettings = "";
|
||||
if (this.classesToInclude!=null) {
|
||||
includeSettings = this.classesToInclude.toString();
|
||||
}
|
||||
settingsMap.put(AgentConfigConstants.CLASS_REGEX,
|
||||
getPatternString(classRegex));
|
||||
includeSettings);
|
||||
|
||||
String excludeSettings = "";
|
||||
if (this.classesToExclude!=null) {
|
||||
includeSettings = this.classesToExclude.toString();
|
||||
}
|
||||
settingsMap.put(AgentConfigConstants.EXCLUDE_CLASS_REGEX,
|
||||
getPatternString(excludeClassRegex));
|
||||
excludeSettings);
|
||||
settingsMap.put(AgentConfigConstants.VERBOSE_MODE,
|
||||
Boolean.toString(verboseMode));
|
||||
settingsMap.put(AgentConfigConstants.SAVE_TRACED_CLASSFILES,
|
||||
|
|
@ -204,17 +246,12 @@ public void parseArgs(String args)
|
|||
return settingsMap;
|
||||
}
|
||||
|
||||
private String getPatternString(String[] parts)
|
||||
{
|
||||
StringBuilder strBuilder = new StringBuilder();
|
||||
for (int ii = 0; ii < parts.length; ii++)
|
||||
{
|
||||
strBuilder.append(parts[ii]);
|
||||
if (ii < (parts.length - 1))
|
||||
{
|
||||
strBuilder.append("|");
|
||||
}
|
||||
}
|
||||
return strBuilder.toString();
|
||||
}
|
||||
|
||||
public void logVerbose(String v) {
|
||||
if (isVerboseMode())
|
||||
{
|
||||
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: " + v);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
|
||||
InstrumentedClassWriter writer = new InstrumentedClassWriter(xiClassName,
|
||||
cr, analysis,
|
||||
shouldInstrument);
|
||||
shouldInstrument,
|
||||
settings);
|
||||
cr.accept(writer, 0);
|
||||
|
||||
return writer.toByteArray();
|
||||
|
|
@ -163,7 +164,7 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
return false;
|
||||
}
|
||||
|
||||
// Don't sensitive classes
|
||||
// Don't instrument sensitive classes
|
||||
if (isSensitiveClass(className))
|
||||
{
|
||||
if (settings.isVerboseMode())
|
||||
|
|
@ -183,10 +184,9 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
return false;
|
||||
}
|
||||
|
||||
// Don't modify classes which match the exclude regex
|
||||
if ((settings.getExcludeClassRegex() == null)
|
||||
|| matches(settings.getExcludeClassRegex(), className))
|
||||
{
|
||||
|
||||
if (this.settings.getClassesToExclude() != null &&
|
||||
this.settings.getClassesToExclude().allMethodsSpecified(className)) {
|
||||
if (settings.isVerboseMode())
|
||||
{
|
||||
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: Ignoring class matching the active exclude regex: "
|
||||
|
|
@ -699,7 +699,7 @@ public class ClassTransformer implements ClassFileTransformer
|
|||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
String error = "Error instrumenting [" + klass.klass.getName() + "]";
|
||||
String error = "Exception [" + e.getMessage() + "] instrumenting [" + klass.klass.getName() + "]";
|
||||
if (settings.isVerboseMode())
|
||||
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: !! " + error);
|
||||
System.err.println(error);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,232 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.intrace.output.trace.TraceHandler;
|
||||
|
||||
/**
|
||||
* Contains criteria that the 'user' specifies to request certain classes to
|
||||
* be instrumented.
|
||||
* @author erikostermueller
|
||||
*
|
||||
*/
|
||||
public class InstrCriteria {
|
||||
|
||||
public VerboseLogger verboseLogger = null;
|
||||
/**
|
||||
* Each item in this Map is a classname that has methods.
|
||||
*/
|
||||
final Map<String,List<SimpleMethod> > myInstrCriteria = new Hashtable<String,List<SimpleMethod>>();
|
||||
static final String CLASS_METHOD_DELIMITER = "#";
|
||||
private static final String CRITERIA_DELIM = "|";
|
||||
private static final String REGEX_CRITERIA_DELIM = "\\"+CRITERIA_DELIM;
|
||||
private static final String INSTRUMENT_ALL_METHODS = "INSTR_ALL_METHODS";
|
||||
private String[] classNamesOnly = null;
|
||||
private List<String> classNamesOnlyList = new ArrayList<String>();
|
||||
private String originalCriteria = null;
|
||||
public InstrCriteria(String criteria) {
|
||||
this.originalCriteria = criteria;
|
||||
criteria = criteria.replace('{', '[');
|
||||
String[] tmp = criteria.split(this.REGEX_CRITERIA_DELIM);
|
||||
|
||||
for (String s : tmp)
|
||||
addClassOrMethod(s);
|
||||
|
||||
}
|
||||
/*
|
||||
* Example: org.intracetest.agent.ArgumentTypes#charArrayArg([C)V
|
||||
*
|
||||
*/
|
||||
static class SimpleMethod {
|
||||
boolean ynAllMethods = false;
|
||||
/*
|
||||
* example: charArrayArg
|
||||
*/
|
||||
private String name;
|
||||
/*
|
||||
* example: ([C)V
|
||||
*
|
||||
*/
|
||||
private String args;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getArgs() {
|
||||
String rc = "";
|
||||
if (args!=null)
|
||||
rc = this.args.replace('[', '{');
|
||||
return rc;
|
||||
}
|
||||
|
||||
public void setArgs(String args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name+getArgs();
|
||||
}
|
||||
|
||||
public void setNameAndArgs(String methodNameAndArgs) {
|
||||
int firstLeftParen = methodNameAndArgs.indexOf("(");
|
||||
if (firstLeftParen >= 0) {
|
||||
name = methodNameAndArgs.substring(0, firstLeftParen);
|
||||
args = methodNameAndArgs.substring(firstLeftParen);
|
||||
//System.out.println("in setNameAndArgs just added [" + methodNameAndArgs + "] as [" + this.toString() + "]");
|
||||
|
||||
} else
|
||||
name = methodNameAndArgs;
|
||||
}
|
||||
}
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int count = 0;
|
||||
for(String className : this.getClassRegex()) {
|
||||
|
||||
List<SimpleMethod> methods = this.myInstrCriteria.get(className);
|
||||
for(SimpleMethod myMethod : methods) {
|
||||
if (++count > 1) sb.append(CRITERIA_DELIM); //This line add this | to make crit1|crit2|crit3
|
||||
if (myMethod.ynAllMethods)
|
||||
sb.append(className);
|
||||
else {
|
||||
sb.append(className);
|
||||
sb.append(CLASS_METHOD_DELIMITER);
|
||||
sb.append( myMethod.toString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
public String[] getClassRegex() {
|
||||
if (classNamesOnly==null) {
|
||||
Set<String> keys = this.myInstrCriteria.keySet();
|
||||
classNamesOnly = keys.toArray( new String[0] );
|
||||
}
|
||||
return classNamesOnly;
|
||||
|
||||
}
|
||||
/**
|
||||
* Example: org.intracetest.agent.ArgumentTypes#charArrayArg([C)V
|
||||
*
|
||||
* @param myclass: example: org.intracetest.agent.ArgumentTypes
|
||||
* @param method: example: charArrayArg
|
||||
* @param arguments: example: ([C)V
|
||||
* @return
|
||||
*/
|
||||
public boolean thisMethodSpecified(String myClass, String method, String arguments) {
|
||||
List<SimpleMethod> allMethods = null;
|
||||
arguments = arguments.replace('[', '{');
|
||||
boolean rc = false;
|
||||
if (this.allMethodsSpecified(myClass)) {
|
||||
rc = true;
|
||||
}else {
|
||||
allMethods = this.myInstrCriteria.get(myClass);
|
||||
if (findMethod(allMethods, method,arguments)!=null)
|
||||
rc = true;
|
||||
}
|
||||
logVerbose("instrument method? [" + rc +
|
||||
"] class[" + myClass +
|
||||
"] method[" + method +
|
||||
"] + method args [" + arguments +
|
||||
"] count of methods instrumented [" + ( (allMethods!=null) ? allMethods.size() : "zero" )+
|
||||
"]");
|
||||
return rc;
|
||||
|
||||
}
|
||||
public int methodCountPerClass(String myClass) {
|
||||
int count = 0;
|
||||
List<SimpleMethod> allMethods = this.myInstrCriteria.get(myClass);
|
||||
if (allMethods!=null) {
|
||||
count = allMethods.size();
|
||||
}
|
||||
return count;
|
||||
|
||||
}
|
||||
private void logVerbose(String s) {
|
||||
if (this.verboseLogger!=null) {
|
||||
this.verboseLogger.logVerbose(s);
|
||||
}
|
||||
}
|
||||
public boolean allMethodsSpecified(String myClass) {
|
||||
boolean rc = false;
|
||||
List<SimpleMethod> allMethods = this.myInstrCriteria.get(myClass);
|
||||
if (allMethods !=null)
|
||||
for(SimpleMethod method : allMethods) {
|
||||
if (method.ynAllMethods)
|
||||
rc = true;
|
||||
}
|
||||
//logVerbose("instrument all methods for this class? [" + rc + "] class[" + myClass + "]");
|
||||
return rc;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* The bug lies here:
|
||||
* Comparing fullMethodNameCriteria [byteArrayArg({B)V] to [byteArrayArg([B)V]
|
||||
*
|
||||
* @param methods
|
||||
* @param nameCriteria
|
||||
* @param argsCriteria
|
||||
* @return
|
||||
*/
|
||||
private SimpleMethod findMethod(List<SimpleMethod> methods, String nameCriteria, String argsCriteria){
|
||||
SimpleMethod rc = null;
|
||||
if (nameCriteria !=null && argsCriteria !=null) {
|
||||
String fullMethodNameCriteria = nameCriteria + argsCriteria;
|
||||
if (methods != null)
|
||||
for(SimpleMethod sm : methods) {
|
||||
//logVerbose("Comparing fullMethodNameCriteria [" + fullMethodNameCriteria + "] to [" + sm.toString() + "]");
|
||||
if (fullMethodNameCriteria.equals(sm.toString())) {
|
||||
rc = sm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
/**
|
||||
* trying to split this into two: MyClass#myMethod(D)V, but MyClass is also allowable here
|
||||
* @param methodOrClass
|
||||
*/
|
||||
private void addClassOrMethod(String methodOrClass) {
|
||||
//System.out.println("###addClassOrMethod [" + methodOrClass + "]");
|
||||
SimpleMethod method = new SimpleMethod();
|
||||
|
||||
List<SimpleMethod> allMethods = null;
|
||||
|
||||
String[] parts = methodOrClass.split(CLASS_METHOD_DELIMITER);
|
||||
if (parts.length >= 1 && parts[0]!=null) {
|
||||
allMethods = this.myInstrCriteria.get(parts[0]);
|
||||
if (allMethods == null) {
|
||||
allMethods = new ArrayList<SimpleMethod>();
|
||||
//this.logVerbose("in addClassOrMethod just created allMethods hash[" + allMethods.hashCode() + "]myInstrCriteriaHash[" + myInstrCriteria.hashCode() + "]");
|
||||
this.myInstrCriteria.put(parts[0], allMethods);
|
||||
}
|
||||
|
||||
switch (parts.length) {
|
||||
case 1: //just the package and class name were specified, meaning that all methods should be instrumented.
|
||||
method.ynAllMethods = true;
|
||||
break;
|
||||
case 2: //a method was specified after a # sign...only instrument this specific method.
|
||||
method.setNameAndArgs(parts[1]);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Was expecting to find either zero or one of the [" + this.CLASS_METHOD_DELIMITER + "] character inside of [" + methodOrClass + "]");
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Error adding this method/class [" + methodOrClass + "]");
|
||||
}
|
||||
allMethods.add(method);
|
||||
// System.out.println("## Just added methodName[" + method.name + "] methodArg [" + method.args + "]methodArgGetter [" + method.getArgs() + "]");
|
||||
// System.out.println("@@@@@@@Class count [" + myInstrCriteria.size() + "] for class[" + parts[0] + "] count is [" + allMethods.size() + "]");
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import org.intrace.output.AgentHelper;
|
||||
import org.intrace.output.trace.TraceHandler;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Label;
|
||||
|
|
@ -27,6 +28,7 @@ public class InstrumentedClassWriter extends ClassWriter
|
|||
private final ClassAnalysis analysis;
|
||||
private final boolean threadClass;
|
||||
private final boolean shouldInstrument;
|
||||
private AgentSettings settings = null;
|
||||
|
||||
/**
|
||||
* cTor
|
||||
|
|
@ -37,13 +39,14 @@ public class InstrumentedClassWriter extends ClassWriter
|
|||
* @param analysis
|
||||
*/
|
||||
public InstrumentedClassWriter(String xiClassName, ClassReader xiReader,
|
||||
ClassAnalysis xiAnalysis, boolean xiShouldInstrument)
|
||||
ClassAnalysis xiAnalysis, boolean xiShouldInstrument, AgentSettings settings)
|
||||
{
|
||||
super(xiReader, COMPUTE_MAXS);
|
||||
className = xiClassName;
|
||||
analysis = xiAnalysis;
|
||||
shouldInstrument = xiShouldInstrument;
|
||||
threadClass = xiClassName.equals("java.lang.Thread");
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -53,18 +56,52 @@ public class InstrumentedClassWriter extends ClassWriter
|
|||
public MethodVisitor visitMethod(int access, String name, String desc,
|
||||
String signature, String[] exceptions)
|
||||
{
|
||||
|
||||
if (settings.isVerboseMode())
|
||||
{
|
||||
|
||||
/** The following code provides invaluable debug for conjuring right syntax for method parameters.
|
||||
* http://hsqldb.org/doc/src/org/hsqldb/jdbc/JDBCConnection.html#isWrapperFor(java.lang.Class)
|
||||
[14:44:45.065]:[19]:access:1
|
||||
[14:44:45.065]:[19]:name:isWrapperFor
|
||||
[14:44:45.065]:[19]:desc:(Ljava/lang/Class;)Z <<<<<==== complicate syntax for method specification
|
||||
[14:44:45.065]:[19]:signature:(Ljava/lang/Class<*>;)Z
|
||||
|
||||
http://hsqldb.org/doc/src/org/hsqldb/jdbc/JDBCConnection.html#prepareStatement(java.lang.String, java.lang.String[])
|
||||
[14:44:45.068]:[19]:access:33
|
||||
[14:44:45.068]:[19]:name:prepareStatement
|
||||
[14:44:45.069]:[19]:desc:(Ljava/lang/String;[Ljava/lang/String;)Ljava/sql/PreparedStatement; <<<<<==== complicated syntax for method specification
|
||||
[14:44:45.069]:[19]:signature:null
|
||||
|
||||
*/
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(this.className);
|
||||
sb.append(InstrCriteria.CLASS_METHOD_DELIMITER);
|
||||
sb.append(name);
|
||||
sb.append(desc);
|
||||
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: method signature: " + sb.toString());
|
||||
}
|
||||
MethodVisitor mv = super.visitMethod(access, name, desc, signature,
|
||||
exceptions);
|
||||
|
||||
// Extract analysis results for this method
|
||||
Set<Integer> branchTraceLines = analysis.methodReverseGOTOLines.get(name
|
||||
+ desc);
|
||||
Integer entryLine = analysis.methodEntryLines.get(name + desc);
|
||||
// If this class/method is not excluded, but then consider including it.
|
||||
// If all methods are allowed (by not specifying any methods) or this specific method is defined, then instrument it.
|
||||
|
||||
if (!threadClass || !name.equals("getUncaughtExceptionHandler"))
|
||||
{
|
||||
mv = new InstrumentedMethodWriter(mv, access, name, desc,
|
||||
branchTraceLines, entryLine);
|
||||
if (this.settings.getClassesToExclude()==null
|
||||
||!this.settings.getClassesToExclude().thisMethodSpecified(this.className, name, desc)) {
|
||||
if (this.settings.getClassesToInclude().thisMethodSpecified(this.className, name, desc) ) {
|
||||
// Extract analysis results for this method
|
||||
Set<Integer> branchTraceLines = analysis.methodReverseGOTOLines.get(name
|
||||
+ desc);
|
||||
Integer entryLine = analysis.methodEntryLines.get(name + desc);
|
||||
|
||||
if (!threadClass || !name.equals("getUncaughtExceptionHandler"))
|
||||
{
|
||||
//System.out.println("Instrumenting class [" + this.className + "] method [" + name + "] args [" + desc + "]");
|
||||
mv = new InstrumentedMethodWriter(mv, access, name, desc,
|
||||
branchTraceLines, entryLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Transform the method
|
||||
return mv;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package org.intrace.agent;
|
||||
|
||||
public interface VerboseLogger {
|
||||
public void logVerbose(String v);
|
||||
}
|
||||
|
|
@ -491,7 +491,8 @@ public class InTraceUI implements ISocketCallback, IControlConnectionListener
|
|||
},
|
||||
getListFromString(settingsData.classRegex),
|
||||
getListFromString(settingsData.classExcludeRegex),
|
||||
ALLOW_CLASSES);
|
||||
ALLOW_ALL);
|
||||
//ALLOW_CLASSES);
|
||||
placeDialogInCenter(sWindow.getBounds(), regexInput.sWindow);
|
||||
}
|
||||
});
|
||||
|
|
@ -2113,10 +2114,13 @@ public class InTraceUI implements ISocketCallback, IControlConnectionListener
|
|||
@Override
|
||||
public void run()
|
||||
{
|
||||
settingsData.classRegex = includePattern;
|
||||
settingsData.classExcludeRegex = excludePattern;
|
||||
controlThread.sendMessage(AgentConfigConstants.CLASS_REGEX + includePattern
|
||||
+ AgentConfigConstants.EXCLUDE_CLASS_REGEX + excludePattern);
|
||||
String tmpInclude = includePattern.replace('[', '{');
|
||||
String tmpExclude = excludePattern.replace('[', '{');
|
||||
|
||||
settingsData.classRegex = tmpInclude;
|
||||
settingsData.classExcludeRegex = tmpExclude;
|
||||
controlThread.sendMessage(AgentConfigConstants.CLASS_REGEX + tmpInclude
|
||||
+ AgentConfigConstants.EXCLUDE_CLASS_REGEX + tmpExclude);
|
||||
controlThread.sendMessage("getsettings");
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.intracetest.agent;
|
||||
|
||||
import java.util.Map;
|
||||
import org.intrace.agent.InstrCriteria;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
|
@ -9,6 +10,10 @@ import org.intrace.shared.AgentConfigConstants;
|
|||
|
||||
public class AgentSettingsTest extends TestCase
|
||||
{
|
||||
private String M1 = "org.intracetest.agent.ArgumentTypes#boolArrayArrayArg({{Z)V";
|
||||
private String M2 = "org.intracetest.agent.ArgumentTypes#objArrayArg({Ljava/lang/Object;)V";
|
||||
private String M3 = "org.intracetest.agent.ArgumentTypes#doubleArg(D)V";
|
||||
|
||||
public void testAgentSettings()
|
||||
{
|
||||
AgentSettings as = new AgentSettings(
|
||||
|
|
@ -22,8 +27,12 @@ public class AgentSettingsTest extends TestCase
|
|||
+ "true");
|
||||
assertNotNull(as.getClassRegex());
|
||||
assertEquals(as.getClassRegex().length, 2);
|
||||
assertEquals(as.getClassRegex()[0], "foo");
|
||||
assertEquals(as.getClassRegex()[1], "bar");
|
||||
|
||||
assertTrue( "foo".equals(as.getClassRegex()[0]) || "foo".equals(as.getClassRegex()[1]) );
|
||||
assertTrue( "bar".equals(as.getClassRegex()[0]) || "bar".equals(as.getClassRegex()[1]) );
|
||||
assertTrue( as.getClassesToInclude().allMethodsSpecified("foo") );
|
||||
assertFalse( as.getClassesToInclude().allMethodsSpecified("unknownClass"));
|
||||
|
||||
assertEquals(as.isInstrumentationEnabled(), true);
|
||||
assertEquals(as.saveTracedClassfiles(), true);
|
||||
assertEquals(as.isVerboseMode(), true);
|
||||
|
|
@ -31,8 +40,12 @@ public class AgentSettingsTest extends TestCase
|
|||
as = new AgentSettings(as);
|
||||
assertNotNull(as.getClassRegex());
|
||||
assertEquals(as.getClassRegex().length, 2);
|
||||
assertEquals(as.getClassRegex()[0], "foo");
|
||||
assertEquals(as.getClassRegex()[1], "bar");
|
||||
assertTrue( "foo".equals(as.getClassRegex()[0]) || "foo".equals(as.getClassRegex()[1]) );
|
||||
assertTrue( "bar".equals(as.getClassRegex()[0]) || "bar".equals(as.getClassRegex()[1]) );
|
||||
|
||||
assertTrue( as.getClassesToInclude().allMethodsSpecified("foo") );
|
||||
assertFalse( as.getClassesToInclude().allMethodsSpecified("unknownClass"));
|
||||
|
||||
assertEquals(as.isInstrumentationEnabled(), true);
|
||||
assertEquals(as.saveTracedClassfiles(), true);
|
||||
assertEquals(as.isVerboseMode(), true);
|
||||
|
|
@ -41,11 +54,106 @@ public class AgentSettingsTest extends TestCase
|
|||
assertNotNull(toString);
|
||||
|
||||
Map<String, String> settingsMap = as.getSettingsMap();
|
||||
assertEquals(settingsMap.get(AgentConfigConstants.CLASS_REGEX), "foo|bar");
|
||||
|
||||
assertTrue( settingsMap.get(AgentConfigConstants.CLASS_REGEX).equals("foo|bar") ||
|
||||
settingsMap.get(AgentConfigConstants.CLASS_REGEX).equals("bar|foo") );
|
||||
|
||||
assertEquals(settingsMap.get(AgentConfigConstants.INSTRU_ENABLED), "true");
|
||||
assertEquals(settingsMap.get(AgentConfigConstants.SAVE_TRACED_CLASSFILES),
|
||||
"true");
|
||||
assertEquals(settingsMap.get(AgentConfigConstants.VERBOSE_MODE), "true");
|
||||
}
|
||||
|
||||
public void testInstrCriteria() {
|
||||
InstrCriteria ic = new InstrCriteria("foo|bar");
|
||||
|
||||
assertTrue(ic.allMethodsSpecified("foo") ); //This is criteria for 'foo' class, no methods here. When no methods were specified, then instrument all methods.
|
||||
assertTrue(ic.allMethodsSpecified("bar") ); //This is criteria for the 'bar' class; no methods here. When no methods were specified, then instrument all methods.
|
||||
assertFalse(ic.allMethodsSpecified("doesnotexist") ); //If class name was never specified, then no methods should be instrumented.
|
||||
|
||||
assertTrue("foo".equals(ic.getClassRegex()[0]) || "foo".equals(ic.getClassRegex()[1]) );
|
||||
assertTrue("bar".equals(ic.getClassRegex()[0]) || "bar".equals(ic.getClassRegex()[1]) );
|
||||
|
||||
assertEquals("Added one class with a single 'instrument all', but count isn't right",
|
||||
1,
|
||||
ic.methodCountPerClass("foo")
|
||||
);
|
||||
|
||||
assertEquals("Added one class with a single 'instrument all', but count isn't right",
|
||||
1,
|
||||
ic.methodCountPerClass("bar")
|
||||
);
|
||||
|
||||
assertTrue("toString in InstrCriteria is not working", ic.toString().equals("foo|bar") || ic.toString().equals("bar|foo") );
|
||||
}
|
||||
|
||||
public void testIfWeCanParseMethodCriteria() {
|
||||
InstrCriteria ic2 = new InstrCriteria("org.hsqldb.jdbc.JDBCConnection#onStartEscapeSequence(Ljava/lang/String;Ljava/lang/StringBuffer;I)I");
|
||||
assertFalse( ic2.allMethodsSpecified("org.hsqldb.jdbc.JDBCConnection") );
|
||||
|
||||
assertTrue( ic2.thisMethodSpecified("org.hsqldb.jdbc.JDBCConnection", "onStartEscapeSequence", "(Ljava/lang/String;Ljava/lang/StringBuffer;I)I"));
|
||||
assertFalse( ic2.thisMethodSpecified("Xorg.hsqldb.jdbc.JDBCConnection", "onStartEscapeSequence", "(Ljava/lang/String;Ljava/lang/StringBuffer;I)I"));
|
||||
assertFalse( ic2.thisMethodSpecified("org.hsqldb.jdbc.JDBCConnection", "XonStartEscapeSequence", "(Ljava/lang/String;Ljava/lang/StringBuffer;I)I"));
|
||||
assertFalse( ic2.thisMethodSpecified("org.hsqldb.jdbc.JDBCConnection", "onStartEscapeSequence", "X(Ljava/lang/String;Ljava/lang/StringBuffer;I)I"));
|
||||
}
|
||||
public void testIfWeCanParseMix() {
|
||||
|
||||
InstrCriteria ic2 = new InstrCriteria("org.hsqldb.jdbc.JDBCConnection#onStartEscapeSequence(Ljava/lang/String;Ljava/lang/StringBuffer;I)I|foo");
|
||||
assertFalse( ic2.allMethodsSpecified("org.hsqldb.jdbc.JDBCConnection") );
|
||||
|
||||
assertTrue( ic2.thisMethodSpecified("org.hsqldb.jdbc.JDBCConnection", "onStartEscapeSequence", "(Ljava/lang/String;Ljava/lang/StringBuffer;I)I"));
|
||||
assertFalse( ic2.thisMethodSpecified("Xorg.hsqldb.jdbc.JDBCConnection", "onStartEscapeSequence", "(Ljava/lang/String;Ljava/lang/StringBuffer;I)I"));
|
||||
assertFalse( ic2.thisMethodSpecified("org.hsqldb.jdbc.JDBCConnection", "XonStartEscapeSequence", "(Ljava/lang/String;Ljava/lang/StringBuffer;I)I"));
|
||||
assertFalse( ic2.thisMethodSpecified("org.hsqldb.jdbc.JDBCConnection", "onStartEscapeSequence", "X(Ljava/lang/String;Ljava/lang/StringBuffer;I)I"));
|
||||
|
||||
assertTrue(ic2.allMethodsSpecified("foo") ); //If not methods were specified, then instrument all methods.
|
||||
assertFalse(ic2.allMethodsSpecified("doesnotexist") ); //If class name was never specified, then no methods should be instrumented.
|
||||
|
||||
//assertEquals(ic2.getClassRegex()[0], "foo");
|
||||
assertTrue("foo".equals(ic2.getClassRegex()[0]) || "foo".equals(ic2.getClassRegex()[1]) );
|
||||
assertTrue("org.hsqldb.jdbc.JDBCConnection".equals(ic2.getClassRegex()[0]) || "org.hsqldb.jdbc.JDBCConnection".equals(ic2.getClassRegex()[1]) );
|
||||
|
||||
|
||||
|
||||
}
|
||||
public void testIfWeCanParseThreeComplicatedMethods() {
|
||||
String myCriteria = M1+"|"+M2+"|"+M3;
|
||||
//System.out.println("@@@@@@@Start of testIfWeCanParseThreeComplicatedMethods() ");
|
||||
InstrCriteria ic = new InstrCriteria(myCriteria);
|
||||
//System.out.println("@@@@@@@@@@@@@@Before assert for testIfWeCanParseThreeComplicatedMethods() ");
|
||||
assertEquals("Added three methods for a single class, but didn't find the right count of methods",
|
||||
3,
|
||||
ic.methodCountPerClass("org.intracetest.agent.ArgumentTypes")
|
||||
);
|
||||
//System.out.println("@@@@@@@@@@@@@@ AFTER assert for testIfWeCanParseThreeComplicatedMethods() ");
|
||||
}
|
||||
public void testMethodsFromDifferentClasses() {
|
||||
InstrCriteria ic = new InstrCriteria("ArgumentTypes#byteArrayArg({B)V|OtherTypes#byteArrayArg({B)V");
|
||||
assertFalse( ic.allMethodsSpecified("ArgumentTypes") );
|
||||
assertFalse( ic.allMethodsSpecified("OtherTypes") );
|
||||
|
||||
String[] myClasses = ic.getClassRegex();
|
||||
assertTrue( "ArgumentTypes".equals(myClasses[0]) || "ArgumentTypes".equals(myClasses[1]) );
|
||||
assertTrue( "OtherTypes".equals(myClasses[0]) || "OtherTypes".equals(myClasses[1]) );
|
||||
|
||||
assertTrue( ic.thisMethodSpecified("ArgumentTypes","byteArrayArg", "({B)V") );
|
||||
assertTrue( ic.thisMethodSpecified("OtherTypes", "byteArrayArg", "({B)V") );
|
||||
|
||||
assertTrue( ic.toString().equals("ArgumentTypes#byteArrayArg({B)V|OtherTypes#byteArrayArg({B)V")
|
||||
|| ic.toString().equals("OtherTypes#byteArrayArg({B)V|ArgumentTypes#byteArrayArg({B)V") );
|
||||
|
||||
}
|
||||
public void testMethodsFromSameClasses() {
|
||||
InstrCriteria ic = new InstrCriteria("MyTypes#bar({B)V|MyTypes#foo({B)V");
|
||||
assertFalse( ic.allMethodsSpecified("MyTypes") );
|
||||
|
||||
assertTrue( ic.thisMethodSpecified("MyTypes","foo", "({B)V") );
|
||||
assertTrue( ic.thisMethodSpecified("MyTypes", "bar", "({B)V") );
|
||||
|
||||
assertTrue( ic.toString().equals("MyTypes#bar({B)V|MyTypes#foo({B)V")
|
||||
|| ic.toString().equals("MyTypes#foo({B)V|MyTypes#bar({B)V") );
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -214,8 +214,8 @@ public class AgentTest extends TestCase
|
|||
|
||||
// Setup agent
|
||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
||||
testSetting(AgentConfigConstants.CLASS_REGEX, "BranchPatterns");
|
||||
testSetting(AgentConfigConstants.VERBOSE_MODE, "false");
|
||||
testSetting(AgentConfigConstants.CLASS_REGEX, "org.intracetest.agent.BranchPatterns");
|
||||
testSetting(AgentConfigConstants.VERBOSE_MODE, "true");
|
||||
testSetting(AgentConfigConstants.SAVE_TRACED_CLASSFILES, "true");
|
||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "true");
|
||||
|
||||
|
|
@ -241,6 +241,8 @@ public class AgentTest extends TestCase
|
|||
traceLine = capturedTrace.poll();
|
||||
}
|
||||
|
||||
assertEquals(12,parsedTraceData.size());
|
||||
|
||||
// Verify the trace
|
||||
assertNotNull(parsedTraceData.get("switchblock"));
|
||||
{
|
||||
|
|
@ -320,6 +322,7 @@ public class AgentTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void testArgumentTypes() throws Throwable
|
||||
{
|
||||
// Create and init the mock
|
||||
|
|
@ -329,7 +332,7 @@ public class AgentTest extends TestCase
|
|||
|
||||
// Setup agent
|
||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
||||
testSetting(AgentConfigConstants.CLASS_REGEX, "ArgumentTypes");
|
||||
testSetting(AgentConfigConstants.CLASS_REGEX, "org.intracetest.agent.ArgumentTypes");
|
||||
testSetting(AgentConfigConstants.VERBOSE_MODE, "false");
|
||||
testSetting(AgentConfigConstants.SAVE_TRACED_CLASSFILES, "true");
|
||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "true");
|
||||
|
|
@ -494,7 +497,9 @@ public class AgentTest extends TestCase
|
|||
private void parseLine(Map<String, TraceData> parsedTraceData,
|
||||
String traceLine)
|
||||
{
|
||||
System.out.println("Parse: " + traceLine);
|
||||
//System.out.println("Parse: " + traceLine);
|
||||
if (traceLine.contains("DEBUG"))
|
||||
return;
|
||||
String[] traceParts = traceLine.split(":##:");
|
||||
String traceType = traceParts[0];
|
||||
String traceLineData = traceParts[1];
|
||||
|
|
|
|||
|
|
@ -70,96 +70,228 @@ public class ArgumentTypes implements Runnable
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#byteArg(B)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void byteArg(byte arg)
|
||||
{
|
||||
setProperty(Byte.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#byteArrayArg({B)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void byteArrayArg(byte[] arg)
|
||||
{
|
||||
setProperty(Arrays.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#shortArg(S)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void shortArg(short arg)
|
||||
{
|
||||
setProperty(Short.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#shortArrayArg({S)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void shortArrayArg(short[] arg)
|
||||
{
|
||||
setProperty(Arrays.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#intArg(I)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void intArg(int arg)
|
||||
{
|
||||
setProperty(Integer.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#intArrayArg({I)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void intArrayArg(int[] arg)
|
||||
{
|
||||
setProperty(Arrays.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#longArg(J)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void longArg(long arg)
|
||||
{
|
||||
setProperty(Long.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#longArrayArg({J)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void longArrayArg(long[] arg)
|
||||
{
|
||||
setProperty(Arrays.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#floatArg(F)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void floatArg(float arg)
|
||||
{
|
||||
setProperty(Float.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#floatArrayArg({F)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void floatArrayArg(float[] arg)
|
||||
{
|
||||
setProperty(Arrays.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#doubleArg(D)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void doubleArg(double arg)
|
||||
{
|
||||
setProperty(Double.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#doubleArrayArg({D)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void doubleArrayArg(double[] arg)
|
||||
{
|
||||
setProperty(Arrays.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#boolArg(Z)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void boolArg(boolean arg)
|
||||
{
|
||||
setProperty(Boolean.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#boolArrayArg({Z)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void boolArrayArg(boolean[] arg)
|
||||
{
|
||||
setProperty(Arrays.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#boolArrayArrayArg({{Z)V
|
||||
</pre>
|
||||
*/
|
||||
private void boolArrayArrayArg(boolean[][] arg)
|
||||
{
|
||||
setProperty(Arrays.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#charArg(C)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void charArg(char arg)
|
||||
{
|
||||
setProperty(Character.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#charArrayArg({C)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void charArrayArg(char[] arg)
|
||||
{
|
||||
setProperty(Arrays.toString(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#objArg(Ljava/lang/Object;)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void objArg(Object arg)
|
||||
{
|
||||
setProperty(arg.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* InTrace Method specifier syntax:
|
||||
<pre>
|
||||
org.intracetest.agent.ArgumentTypes#objArrayArg({Ljava/lang/Object;)V
|
||||
</pre>
|
||||
*/
|
||||
|
||||
private void objArrayArg(Object[] arg)
|
||||
{
|
||||
setProperty(Arrays.toString(arg));
|
||||
|
|
@ -169,4 +301,20 @@ public class ArgumentTypes implements Runnable
|
|||
{
|
||||
System.setProperty("test-key", value);
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
System.out.println("Currently running sample code in background thread.");
|
||||
System.out.println("Make sure this program has -javaagent:./path/to/intrace-agent.jar on its command line.");
|
||||
System.out.println("Start InTrace GUI, download-able at https://mchr3k.github.io/org.intrace/");
|
||||
System.out.println("'Connect' & then configure GUI to trace any of these patterns:");
|
||||
System.out.println("org.intracetest.agent.ArgumentTypes#byteArrayArg({B)V -- to trace this single method");
|
||||
System.out.println("org.intracetest.agent.ArgumentTypes#shortArg(S)V -- to trace this single method");
|
||||
System.out.println("org.intracetest.agent.ArgumentTypes -- to trace all methods in class ArgumentTypes");
|
||||
System.out.println("Press Ctrl+C to quit this program.");
|
||||
Runnable r = new ArgumentTypes();
|
||||
while(true) {
|
||||
new Thread(r).start();
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,386 @@
|
|||
package org.intracetest.agent;
|
||||
|
||||
import static org.easymock.EasyMock.isA;
|
||||
|
||||
import java.io.File;
|
||||
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.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.easymock.IAnswer;
|
||||
import org.easymock.EasyMock;
|
||||
import org.intrace.output.AgentHelper;
|
||||
import org.intrace.output.IInstrumentationHandler;
|
||||
import org.intrace.shared.AgentConfigConstants;
|
||||
import org.intrace.shared.TraceConfigConstants;
|
||||
|
||||
/**
|
||||
* This test tests the Agent. To run this test you must run the test with this
|
||||
* JVM argument: "-javaagent:built/traceagent_test.jar="
|
||||
*/
|
||||
public class TracingSingleMethodTest extends TestCase
|
||||
{
|
||||
private Receiver receiver;
|
||||
private Sender sender;
|
||||
private Socket socket;
|
||||
|
||||
private String M1 = "org.intracetest.agent.ArgumentTypes#boolArrayArrayArg({{Z)V";
|
||||
private String M2 = "org.intracetest.agent.ArgumentTypes#objArrayArg({Ljava/lang/Object;)V";
|
||||
private String M3 = "org.intracetest.agent.ArgumentTypes#doubleArg(D)V";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
deleteOldClassFiles();
|
||||
AgentHelper.setInstrumentationHandler(null);
|
||||
// Wait for agent to startup
|
||||
Thread.sleep(500);
|
||||
connectToAgent();
|
||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
||||
}
|
||||
|
||||
private void deleteOldClassFiles()
|
||||
{
|
||||
File genbin = new File("./genbin/");
|
||||
File[] files = genbin.listFiles();
|
||||
if (files != null)
|
||||
{
|
||||
for (int i = 0; i < files.length; i++)
|
||||
{
|
||||
if (files[i].isDirectory())
|
||||
{
|
||||
deleteDirectory(files[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
files[i].delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean deleteDirectory(File path)
|
||||
{
|
||||
if (path.exists())
|
||||
{
|
||||
File[] files = path.listFiles();
|
||||
for (int i = 0; i < files.length; i++)
|
||||
{
|
||||
if (files[i].isDirectory())
|
||||
{
|
||||
deleteDirectory(files[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
files[i].delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
return (path.delete());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void testSetting(String configConstant, String configValue)
|
||||
throws Exception
|
||||
{
|
||||
|
||||
Map<String, String> settingsResponseMap = sendAndReceiveSettings(configConstant, configValue);
|
||||
//System.out.println("Compar1 act: " + settingsResponseMap.get(configConstant) );
|
||||
//System.out.println("Compar2 exp: " + configValue);
|
||||
assertEquals(configValue, settingsResponseMap.get(configConstant));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String,String> sendAndReceiveSettings(String configConstant, String configValue)
|
||||
throws Exception
|
||||
{
|
||||
// Set setting
|
||||
sender.sendMessage(configConstant + configValue);
|
||||
Object okResponse = receiver.incomingMessages.take();
|
||||
assertNotNull(okResponse);
|
||||
assertTrue(okResponse instanceof String);
|
||||
assertEquals(okResponse, "OK");
|
||||
|
||||
// Get settings
|
||||
sender.sendMessage("getsettings");
|
||||
Object settingsResponse = receiver.incomingMessages.take();
|
||||
assertNotNull(settingsResponse);
|
||||
assertTrue(settingsResponse instanceof Map<?, ?>);
|
||||
Map<String, String> settingsResponseMap = (Map<String, String>) settingsResponse;
|
||||
return settingsResponseMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void testArgumentTypesForOneMethod() throws Throwable {
|
||||
|
||||
// Create and init the mock
|
||||
final BlockingQueue<String> capturedTrace = new LinkedBlockingQueue<String>();
|
||||
IInstrumentationHandler testHandler = new ArgCapture(capturedTrace);
|
||||
AgentHelper.setInstrumentationHandler(testHandler);
|
||||
|
||||
// Setup agent
|
||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
||||
|
||||
//The intArg() method takes a single int parameter...let's trace just this one method.
|
||||
testSetting(AgentConfigConstants.CLASS_REGEX, "org.intracetest.agent.ArgumentTypes#intArg(I)V");
|
||||
testSetting(AgentConfigConstants.VERBOSE_MODE, "false");
|
||||
testSetting(AgentConfigConstants.SAVE_TRACED_CLASSFILES, "true");
|
||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "true");
|
||||
|
||||
// Run Patterns thread
|
||||
ArgumentTypes argTypes = new ArgumentTypes();
|
||||
Thread patternThread = new Thread(argTypes);
|
||||
patternThread.start();
|
||||
patternThread.join(5 * 1000);
|
||||
if (argTypes.th != null)
|
||||
{
|
||||
throw argTypes.th;
|
||||
}
|
||||
|
||||
// Parse the trace
|
||||
Map<String, TraceData> parsedTraceData = new HashMap<String, TraceData>();
|
||||
String traceLine = capturedTrace.poll();
|
||||
while (traceLine != null)
|
||||
{
|
||||
parseLine(parsedTraceData, traceLine);
|
||||
traceLine = capturedTrace.poll();
|
||||
}
|
||||
|
||||
/**
|
||||
Method-level tracing to the rescue!
|
||||
This map contains trace lines (3 of them) for exactly 1 method invocation
|
||||
because the new method-level-tracing feature specified only one method.
|
||||
*/
|
||||
assertEquals("Exactly 1 TraceData object for method intArg() should have been in this map",1,parsedTraceData.size() );
|
||||
|
||||
assertNotNull(parsedTraceData.get("intArg"));
|
||||
{
|
||||
TraceData trData = parsedTraceData.get("intArg");
|
||||
assertEquals(1, trData.args.size());
|
||||
assertEquals("4", trData.args.get(0));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void parseLine(Map<String, TraceData> parsedTraceData,
|
||||
String traceLine)
|
||||
{
|
||||
//System.out.println("Parse: " + traceLine);
|
||||
if (traceLine.contains("DEBUG"))
|
||||
return;
|
||||
String[] traceParts = traceLine.split(":##:");
|
||||
String traceType = traceParts[0];
|
||||
String traceLineData = traceParts[1];
|
||||
traceLineData = traceLineData.substring(1, traceLineData.length() - 1);
|
||||
String[] dataParts = traceLineData.split(",");
|
||||
String methodSig;
|
||||
if (traceType.equals("Throwable"))
|
||||
{
|
||||
methodSig = dataParts[2].trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
methodSig = dataParts[1].trim();
|
||||
}
|
||||
|
||||
TraceData traceData = parsedTraceData.get(methodSig);
|
||||
if (traceData == null)
|
||||
{
|
||||
traceData = new TraceData();
|
||||
parsedTraceData.put(methodSig, traceData);
|
||||
}
|
||||
|
||||
if (traceType.equals("Enter"))
|
||||
{
|
||||
traceData.seenEnter = true;
|
||||
}
|
||||
else if (traceType.equals("Exit"))
|
||||
{
|
||||
traceData.seenExit = true;
|
||||
}
|
||||
else if (traceType.equals("Branch"))
|
||||
{
|
||||
traceData.branchLines.add(Integer.parseInt(dataParts[2].trim()));
|
||||
}
|
||||
else if (traceType.equals("Throwable"))
|
||||
{
|
||||
if (traceLine.contains("Caught"))
|
||||
{
|
||||
traceData.caughtLines.add(Integer.parseInt(dataParts[3].trim()));
|
||||
}
|
||||
}
|
||||
else if (traceType.startsWith("Arg"))
|
||||
{
|
||||
traceData.args.add(dataParts[2].trim());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
receiver.stop();
|
||||
sender.stop();
|
||||
socket.close();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private void connectToAgent() throws Exception
|
||||
{
|
||||
String host = "localhost";
|
||||
int port = Integer.parseInt(System.getProperty("org.intrace.port"));
|
||||
|
||||
socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(host, port));
|
||||
|
||||
// Start threads
|
||||
receiver = new Receiver(socket.getInputStream());
|
||||
receiver.start();
|
||||
sender = new Sender(socket.getOutputStream());
|
||||
sender.start();
|
||||
}
|
||||
|
||||
private static class Sender implements Runnable
|
||||
{
|
||||
private final OutputStream outputStream;
|
||||
private final BlockingQueue<String> outgoingMessages = new LinkedBlockingQueue<String>();
|
||||
private Thread th;
|
||||
|
||||
public Sender(OutputStream outputStream)
|
||||
{
|
||||
this.outputStream = outputStream;
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
outputStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
th.interrupt();
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
th = new Thread(this);
|
||||
th.setDaemon(true);
|
||||
th.setName("Sender");
|
||||
th.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
String message = outgoingMessages.take();
|
||||
ObjectOutputStream objOut = new ObjectOutputStream(outputStream);
|
||||
objOut.writeObject(message);
|
||||
objOut.flush();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Do something
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(String message)
|
||||
{
|
||||
try
|
||||
{
|
||||
outgoingMessages.put(message);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Receiver implements Runnable
|
||||
{
|
||||
private final InputStream inputStream;
|
||||
private final BlockingQueue<Object> incomingMessages = new LinkedBlockingQueue<Object>();
|
||||
private Thread th;
|
||||
|
||||
public Receiver(InputStream inputStream)
|
||||
{
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
inputStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
th.interrupt();
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
th = new Thread(this);
|
||||
th.setDaemon(true);
|
||||
th.setName("Receiver");
|
||||
th.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
ObjectInputStream objIn = new ObjectInputStream(inputStream);
|
||||
Object receivedMessage = objIn.readObject();
|
||||
// System.out.println("Test received: " + receivedMessage);
|
||||
if (receivedMessage instanceof Map<?, ?>)
|
||||
{
|
||||
Map<?, ?> receivedMap = (Map<?, ?>) receivedMessage;
|
||||
if (receivedMap.containsKey(AgentConfigConstants.NUM_PROGRESS_ID)||
|
||||
receivedMap.containsKey(AgentConfigConstants.STID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
incomingMessages.put(receivedMessage);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,387 @@
|
|||
package org.intracetest.agent;
|
||||
|
||||
import static org.easymock.EasyMock.isA;
|
||||
|
||||
import java.io.File;
|
||||
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.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.easymock.IAnswer;
|
||||
import org.easymock.EasyMock;
|
||||
import org.intrace.output.AgentHelper;
|
||||
import org.intrace.output.IInstrumentationHandler;
|
||||
import org.intrace.shared.AgentConfigConstants;
|
||||
import org.intrace.shared.TraceConfigConstants;
|
||||
|
||||
/**
|
||||
* This test tests the Agent. To run this test you must run the test with this
|
||||
* JVM argument: "-javaagent:built/traceagent_test.jar="
|
||||
*/
|
||||
public class TracingThreeMethodsTest extends TestCase
|
||||
{
|
||||
private Receiver receiver;
|
||||
private Sender sender;
|
||||
private Socket socket;
|
||||
|
||||
private String M1 = "org.intracetest.agent.ArgumentTypes#boolArrayArrayArg({{Z)V";
|
||||
private String M2 = "org.intracetest.agent.ArgumentTypes#objArrayArg({Ljava/lang/Object;)V";
|
||||
private String M3 = "org.intracetest.agent.ArgumentTypes#doubleArg(D)V";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
deleteOldClassFiles();
|
||||
AgentHelper.setInstrumentationHandler(null);
|
||||
// Wait for agent to startup
|
||||
Thread.sleep(500);
|
||||
connectToAgent();
|
||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
||||
}
|
||||
|
||||
private void deleteOldClassFiles()
|
||||
{
|
||||
File genbin = new File("./genbin/");
|
||||
File[] files = genbin.listFiles();
|
||||
if (files != null)
|
||||
{
|
||||
for (int i = 0; i < files.length; i++)
|
||||
{
|
||||
if (files[i].isDirectory())
|
||||
{
|
||||
deleteDirectory(files[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
files[i].delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean deleteDirectory(File path)
|
||||
{
|
||||
if (path.exists())
|
||||
{
|
||||
File[] files = path.listFiles();
|
||||
for (int i = 0; i < files.length; i++)
|
||||
{
|
||||
if (files[i].isDirectory())
|
||||
{
|
||||
deleteDirectory(files[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
files[i].delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
return (path.delete());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void testSetting(String configConstant, String configValue)
|
||||
throws Exception
|
||||
{
|
||||
|
||||
Map<String, String> settingsResponseMap = sendAndReceiveSettings(configConstant, configValue);
|
||||
//System.out.println("Compar1 act: " + settingsResponseMap.get(configConstant) );
|
||||
//System.out.println("Compar2 exp: " + configValue);
|
||||
assertEquals(configValue, settingsResponseMap.get(configConstant));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String,String> sendAndReceiveSettings(String configConstant, String configValue)
|
||||
throws Exception
|
||||
{
|
||||
// Set setting
|
||||
sender.sendMessage(configConstant + configValue);
|
||||
Object okResponse = receiver.incomingMessages.take();
|
||||
assertNotNull(okResponse);
|
||||
assertTrue(okResponse instanceof String);
|
||||
assertEquals(okResponse, "OK");
|
||||
|
||||
// Get settings
|
||||
sender.sendMessage("getsettings");
|
||||
Object settingsResponse = receiver.incomingMessages.take();
|
||||
assertNotNull(settingsResponse);
|
||||
assertTrue(settingsResponse instanceof Map<?, ?>);
|
||||
Map<String, String> settingsResponseMap = (Map<String, String>) settingsResponse;
|
||||
return settingsResponseMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void testArgumentTypesForThreeMethods() throws Throwable {
|
||||
|
||||
// Create and init the mock
|
||||
final BlockingQueue<String> capturedTrace = new LinkedBlockingQueue<String>();
|
||||
IInstrumentationHandler testHandler = new ArgCapture(capturedTrace);
|
||||
AgentHelper.setInstrumentationHandler(testHandler);
|
||||
|
||||
// Setup agent
|
||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
||||
|
||||
String myCriteria = M1 + "|" + M2 + "|" + M3;
|
||||
//let's trace just these 3 methods
|
||||
testSetting(AgentConfigConstants.CLASS_REGEX, myCriteria);
|
||||
Map<String, String> settingsResponseMap = sendAndReceiveSettings(AgentConfigConstants.CLASS_REGEX, myCriteria);
|
||||
assertNotNull( settingsResponseMap);
|
||||
String unsortedRegex = settingsResponseMap.get(AgentConfigConstants.CLASS_REGEX);
|
||||
assertNotNull(unsortedRegex);
|
||||
String[] expected = { M1, M2, M3 };
|
||||
String[] actual = unsortedRegex.split("\\|");
|
||||
Arrays.sort(expected);
|
||||
Arrays.sort(actual);
|
||||
assertTrue(Arrays.equals(expected,actual));
|
||||
|
||||
|
||||
testSetting(AgentConfigConstants.VERBOSE_MODE, "false");
|
||||
testSetting(AgentConfigConstants.SAVE_TRACED_CLASSFILES, "true");
|
||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "true");
|
||||
|
||||
// Run Patterns thread
|
||||
ArgumentTypes argTypes = new ArgumentTypes();
|
||||
Thread patternThread = new Thread(argTypes);
|
||||
patternThread.start();
|
||||
patternThread.join(5 * 1000);
|
||||
if (argTypes.th != null)
|
||||
{
|
||||
throw argTypes.th;
|
||||
}
|
||||
|
||||
// Parse the trace
|
||||
Map<String, TraceData> parsedTraceData = new HashMap<String, TraceData>();
|
||||
String traceLine = capturedTrace.poll();
|
||||
while (traceLine != null)
|
||||
{
|
||||
parseLine(parsedTraceData, traceLine);
|
||||
traceLine = capturedTrace.poll();
|
||||
}
|
||||
|
||||
/**
|
||||
Method-level tracing to the rescue!
|
||||
This map contains only 1 entry because the new method-level-tracing feature specified only one method.
|
||||
*/
|
||||
assertEquals("Exactly three TraceData objects should have been in this map",3,parsedTraceData.size() );
|
||||
}
|
||||
|
||||
|
||||
private void parseLine(Map<String, TraceData> parsedTraceData,
|
||||
String traceLine)
|
||||
{
|
||||
//System.out.println("Parse: " + traceLine);
|
||||
if (traceLine.contains("DEBUG"))
|
||||
return;
|
||||
String[] traceParts = traceLine.split(":##:");
|
||||
String traceType = traceParts[0];
|
||||
String traceLineData = traceParts[1];
|
||||
traceLineData = traceLineData.substring(1, traceLineData.length() - 1);
|
||||
String[] dataParts = traceLineData.split(",");
|
||||
String methodSig;
|
||||
if (traceType.equals("Throwable"))
|
||||
{
|
||||
methodSig = dataParts[2].trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
methodSig = dataParts[1].trim();
|
||||
}
|
||||
|
||||
TraceData traceData = parsedTraceData.get(methodSig);
|
||||
if (traceData == null)
|
||||
{
|
||||
traceData = new TraceData();
|
||||
parsedTraceData.put(methodSig, traceData);
|
||||
}
|
||||
|
||||
if (traceType.equals("Enter"))
|
||||
{
|
||||
traceData.seenEnter = true;
|
||||
}
|
||||
else if (traceType.equals("Exit"))
|
||||
{
|
||||
traceData.seenExit = true;
|
||||
}
|
||||
else if (traceType.equals("Branch"))
|
||||
{
|
||||
traceData.branchLines.add(Integer.parseInt(dataParts[2].trim()));
|
||||
}
|
||||
else if (traceType.equals("Throwable"))
|
||||
{
|
||||
if (traceLine.contains("Caught"))
|
||||
{
|
||||
traceData.caughtLines.add(Integer.parseInt(dataParts[3].trim()));
|
||||
}
|
||||
}
|
||||
else if (traceType.startsWith("Arg"))
|
||||
{
|
||||
traceData.args.add(dataParts[2].trim());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
receiver.stop();
|
||||
sender.stop();
|
||||
socket.close();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private void connectToAgent() throws Exception
|
||||
{
|
||||
String host = "localhost";
|
||||
int port = Integer.parseInt(System.getProperty("org.intrace.port"));
|
||||
|
||||
socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(host, port));
|
||||
|
||||
// Start threads
|
||||
receiver = new Receiver(socket.getInputStream());
|
||||
receiver.start();
|
||||
sender = new Sender(socket.getOutputStream());
|
||||
sender.start();
|
||||
}
|
||||
|
||||
private static class Sender implements Runnable
|
||||
{
|
||||
private final OutputStream outputStream;
|
||||
private final BlockingQueue<String> outgoingMessages = new LinkedBlockingQueue<String>();
|
||||
private Thread th;
|
||||
|
||||
public Sender(OutputStream outputStream)
|
||||
{
|
||||
this.outputStream = outputStream;
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
outputStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
th.interrupt();
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
th = new Thread(this);
|
||||
th.setDaemon(true);
|
||||
th.setName("Sender");
|
||||
th.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
String message = outgoingMessages.take();
|
||||
ObjectOutputStream objOut = new ObjectOutputStream(outputStream);
|
||||
objOut.writeObject(message);
|
||||
objOut.flush();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Do something
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(String message)
|
||||
{
|
||||
try
|
||||
{
|
||||
outgoingMessages.put(message);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Receiver implements Runnable
|
||||
{
|
||||
private final InputStream inputStream;
|
||||
private final BlockingQueue<Object> incomingMessages = new LinkedBlockingQueue<Object>();
|
||||
private Thread th;
|
||||
|
||||
public Receiver(InputStream inputStream)
|
||||
{
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
inputStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Throw away
|
||||
}
|
||||
th.interrupt();
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
th = new Thread(this);
|
||||
th.setDaemon(true);
|
||||
th.setName("Receiver");
|
||||
th.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
ObjectInputStream objIn = new ObjectInputStream(inputStream);
|
||||
Object receivedMessage = objIn.readObject();
|
||||
// System.out.println("Test received: " + receivedMessage);
|
||||
if (receivedMessage instanceof Map<?, ?>)
|
||||
{
|
||||
Map<?, ?> receivedMap = (Map<?, ?>) receivedMessage;
|
||||
if (receivedMap.containsKey(AgentConfigConstants.NUM_PROGRESS_ID)||
|
||||
receivedMap.containsKey(AgentConfigConstants.STID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
incomingMessages.put(receivedMessage);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue