mirror of https://github.com/mchr3k/org.intrace
method-level tracing to lower overhead
This commit is contained in:
parent
3a1debcbb8
commit
b7dffdde7b
|
|
@ -175,7 +175,7 @@
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="test" description="Run Tests" depends="build" >
|
<target name="test" description="Run Tests" depends="build" >
|
||||||
<property name="emma.enabled" value="true" />
|
<property name="emma.enabled" value="false" />
|
||||||
|
|
||||||
<mkdir dir="./reports" />
|
<mkdir dir="./reports" />
|
||||||
<mkdir dir="./reports/junit" />
|
<mkdir dir="./reports/junit" />
|
||||||
|
|
@ -239,7 +239,7 @@
|
||||||
|
|
||||||
<batchtest fork="yes" todir="./reports/junit/raw">
|
<batchtest fork="yes" todir="./reports/junit/raw">
|
||||||
<fileset dir="./testsrc">
|
<fileset dir="./testsrc">
|
||||||
<include name="**/agent/*Test.java"/>
|
<include name="**/agent/*Test.java"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
</batchtest>
|
</batchtest>
|
||||||
</junit>
|
</junit>
|
||||||
|
|
@ -395,7 +395,7 @@
|
||||||
|
|
||||||
<target name="example_build">
|
<target name="example_build">
|
||||||
<mkdir dir="./build/test" />
|
<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">
|
includeantruntime="false">
|
||||||
<src path="./testsrc"/>
|
<src path="./testsrc"/>
|
||||||
<classpath>
|
<classpath>
|
||||||
|
|
@ -415,6 +415,16 @@
|
||||||
</java>
|
</java>
|
||||||
</target>
|
</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">
|
<target name="waitexample" depends="jar,example_build">
|
||||||
<java classname="example.TraceExample" fork="true">
|
<java classname="example.TraceExample" fork="true">
|
||||||
<arg value="5000" />
|
<arg value="5000" />
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -5,6 +5,7 @@ import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.intrace.output.trace.TraceHandler;
|
||||||
import org.intrace.shared.AgentConfigConstants;
|
import org.intrace.shared.AgentConfigConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -12,9 +13,11 @@ import org.intrace.shared.AgentConfigConstants;
|
||||||
*
|
*
|
||||||
* where argx is of the form value-parameter
|
* 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 serverPort = 9123;
|
||||||
private int callbackPort = -1;
|
private int callbackPort = -1;
|
||||||
private boolean waitStart = false;
|
private boolean waitStart = false;
|
||||||
|
|
@ -24,28 +27,40 @@ public class AgentSettings
|
||||||
|
|
||||||
// Dynamic settings
|
// Dynamic settings
|
||||||
private boolean gzipEnabled = false;
|
private boolean gzipEnabled = false;
|
||||||
private String[] classRegex = new String[0];
|
private InstrCriteria classesToInclude = null;
|
||||||
private String[] excludeClassRegex = new String[0];
|
public InstrCriteria getClassesToInclude() {
|
||||||
|
return classesToInclude;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public InstrCriteria getClassesToExclude() {
|
||||||
|
return classesToExclude;
|
||||||
|
}
|
||||||
|
|
||||||
|
private InstrCriteria classesToExclude = null;
|
||||||
private boolean instruEnabled = true;
|
private boolean instruEnabled = true;
|
||||||
private boolean saveTracedClassfiles = false;
|
private boolean saveTracedClassfiles = false;
|
||||||
private boolean verboseMode = false;
|
private boolean verboseMode = false;
|
||||||
|
|
||||||
public AgentSettings(String args)
|
|
||||||
{
|
|
||||||
parseArgs(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AgentSettings(AgentSettings oldInstance)
|
public AgentSettings(AgentSettings oldInstance)
|
||||||
{
|
{
|
||||||
// Copy all static state and dynamic settings
|
// Copy all static state and dynamic settings
|
||||||
actualServerPort = oldInstance.getActualServerPort();
|
actualServerPort = oldInstance.getActualServerPort();
|
||||||
gzipEnabled = oldInstance.isGzipEnabled();
|
gzipEnabled = oldInstance.isGzipEnabled();
|
||||||
classRegex = oldInstance.getClassRegex();
|
this.classesToInclude = oldInstance.classesToInclude;
|
||||||
excludeClassRegex = oldInstance.getExcludeClassRegex();
|
this.classesToExclude = oldInstance.classesToExclude;
|
||||||
|
|
||||||
|
|
||||||
instruEnabled = oldInstance.isInstrumentationEnabled();
|
instruEnabled = oldInstance.isInstrumentationEnabled();
|
||||||
saveTracedClassfiles = oldInstance.saveTracedClassfiles();
|
saveTracedClassfiles = oldInstance.saveTracedClassfiles();
|
||||||
verboseMode = oldInstance.isVerboseMode();
|
verboseMode = oldInstance.isVerboseMode();
|
||||||
}
|
}
|
||||||
|
public AgentSettings(String args)
|
||||||
|
{
|
||||||
|
parseArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isGzipEnabled() {
|
public boolean isGzipEnabled() {
|
||||||
return gzipEnabled;
|
return gzipEnabled;
|
||||||
|
|
@ -127,7 +142,8 @@ public void parseArgs(String args)
|
||||||
else if (arg.startsWith(AgentConfigConstants.CLASS_REGEX))
|
else if (arg.startsWith(AgentConfigConstants.CLASS_REGEX))
|
||||||
{
|
{
|
||||||
String classRegexStr = arg.replace(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))
|
else if (arg.startsWith(AgentConfigConstants.EXCLUDE_CLASS_REGEX))
|
||||||
{
|
{
|
||||||
|
|
@ -135,7 +151,8 @@ public void parseArgs(String args)
|
||||||
.replace(
|
.replace(
|
||||||
AgentConfigConstants.EXCLUDE_CLASS_REGEX,
|
AgentConfigConstants.EXCLUDE_CLASS_REGEX,
|
||||||
"");
|
"");
|
||||||
excludeClassRegex = classExcludeRegexStr.split("\\|");
|
this.classesToExclude = new InstrCriteria(classExcludeRegexStr);
|
||||||
|
this.classesToExclude.verboseLogger = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,12 +183,18 @@ public void parseArgs(String args)
|
||||||
|
|
||||||
public String[] getClassRegex()
|
public String[] getClassRegex()
|
||||||
{
|
{
|
||||||
return classRegex;
|
String[] rc = {};
|
||||||
|
if (this.classesToInclude!=null)
|
||||||
|
rc = this.classesToInclude.getClassRegex();
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getExcludeClassRegex()
|
public String[] getExcludeClassRegex()
|
||||||
{
|
{
|
||||||
return excludeClassRegex;
|
String[] rc = {};
|
||||||
|
if (this.classesToExclude!=null)
|
||||||
|
rc = this.classesToInclude.getClassRegex();
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInstrumentationEnabled()
|
public boolean isInstrumentationEnabled()
|
||||||
|
|
@ -195,8 +218,17 @@ public void parseArgs(String args)
|
||||||
// Output key settings
|
// Output key settings
|
||||||
String currentSettings = "";
|
String currentSettings = "";
|
||||||
currentSettings += "GZip Enabled : " + gzipEnabled + "\n";
|
currentSettings += "GZip Enabled : " + gzipEnabled + "\n";
|
||||||
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 += "Tracing Enabled : " + instruEnabled + "\n";
|
||||||
currentSettings += "Save Traced Class Files : " + saveTracedClassfiles
|
currentSettings += "Save Traced Class Files : " + saveTracedClassfiles
|
||||||
+ "\n";
|
+ "\n";
|
||||||
|
|
@ -210,10 +242,20 @@ public void parseArgs(String args)
|
||||||
Boolean.toString(instruEnabled));
|
Boolean.toString(instruEnabled));
|
||||||
settingsMap.put(AgentConfigConstants.GZIP,
|
settingsMap.put(AgentConfigConstants.GZIP,
|
||||||
Boolean.toString(gzipEnabled));
|
Boolean.toString(gzipEnabled));
|
||||||
|
|
||||||
|
String includeSettings = "";
|
||||||
|
if (this.classesToInclude!=null) {
|
||||||
|
includeSettings = this.classesToInclude.toString();
|
||||||
|
}
|
||||||
settingsMap.put(AgentConfigConstants.CLASS_REGEX,
|
settingsMap.put(AgentConfigConstants.CLASS_REGEX,
|
||||||
getPatternString(classRegex));
|
includeSettings);
|
||||||
|
|
||||||
|
String excludeSettings = "";
|
||||||
|
if (this.classesToExclude!=null) {
|
||||||
|
includeSettings = this.classesToExclude.toString();
|
||||||
|
}
|
||||||
settingsMap.put(AgentConfigConstants.EXCLUDE_CLASS_REGEX,
|
settingsMap.put(AgentConfigConstants.EXCLUDE_CLASS_REGEX,
|
||||||
getPatternString(excludeClassRegex));
|
excludeSettings);
|
||||||
settingsMap.put(AgentConfigConstants.VERBOSE_MODE,
|
settingsMap.put(AgentConfigConstants.VERBOSE_MODE,
|
||||||
Boolean.toString(verboseMode));
|
Boolean.toString(verboseMode));
|
||||||
settingsMap.put(AgentConfigConstants.SAVE_TRACED_CLASSFILES,
|
settingsMap.put(AgentConfigConstants.SAVE_TRACED_CLASSFILES,
|
||||||
|
|
@ -222,18 +264,13 @@ public void parseArgs(String args)
|
||||||
settingsMap.put(AgentConfigConstants.START_WAIT, Boolean.toString(waitStart));
|
settingsMap.put(AgentConfigConstants.START_WAIT, Boolean.toString(waitStart));
|
||||||
return settingsMap;
|
return settingsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void logVerbose(String v) {
|
||||||
|
if (isVerboseMode())
|
||||||
|
{
|
||||||
|
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: " + v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,8 @@ public class ClassTransformer implements ClassFileTransformer
|
||||||
|
|
||||||
InstrumentedClassWriter writer = new InstrumentedClassWriter(xiClassName,
|
InstrumentedClassWriter writer = new InstrumentedClassWriter(xiClassName,
|
||||||
cr, analysis,
|
cr, analysis,
|
||||||
shouldInstrument);
|
shouldInstrument,
|
||||||
|
settings);
|
||||||
cr.accept(writer, 0);
|
cr.accept(writer, 0);
|
||||||
|
|
||||||
return writer.toByteArray();
|
return writer.toByteArray();
|
||||||
|
|
@ -163,7 +164,7 @@ public class ClassTransformer implements ClassFileTransformer
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't sensitive classes
|
// Don't instrument sensitive classes
|
||||||
if (isSensitiveClass(className))
|
if (isSensitiveClass(className))
|
||||||
{
|
{
|
||||||
if (settings.isVerboseMode())
|
if (settings.isVerboseMode())
|
||||||
|
|
@ -183,10 +184,9 @@ public class ClassTransformer implements ClassFileTransformer
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't modify classes which match the exclude regex
|
|
||||||
if ((settings.getExcludeClassRegex() == null)
|
if (this.settings.getClassesToExclude() != null &&
|
||||||
|| matches(settings.getExcludeClassRegex(), className))
|
this.settings.getClassesToExclude().allMethodsSpecified(className)) {
|
||||||
{
|
|
||||||
if (settings.isVerboseMode())
|
if (settings.isVerboseMode())
|
||||||
{
|
{
|
||||||
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: Ignoring class matching the active exclude regex: "
|
TraceHandler.INSTANCE.writeTraceOutput("DEBUG: Ignoring class matching the active exclude regex: "
|
||||||
|
|
@ -706,7 +706,7 @@ public class ClassTransformer implements ClassFileTransformer
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
{
|
{
|
||||||
// Write exception to stdout
|
// Write exception to stdout
|
||||||
// System.out.println(klass.klass.getName());
|
System.err.println("Exception [" + e.getMessage() + "] instrumenting [" + klass.klass.getName() + "]");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 java.util.Set;
|
||||||
|
|
||||||
import org.intrace.output.AgentHelper;
|
import org.intrace.output.AgentHelper;
|
||||||
|
import org.intrace.output.trace.TraceHandler;
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
|
|
@ -27,6 +28,7 @@ public class InstrumentedClassWriter extends ClassWriter
|
||||||
private final ClassAnalysis analysis;
|
private final ClassAnalysis analysis;
|
||||||
private final boolean threadClass;
|
private final boolean threadClass;
|
||||||
private final boolean shouldInstrument;
|
private final boolean shouldInstrument;
|
||||||
|
private AgentSettings settings = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cTor
|
* cTor
|
||||||
|
|
@ -37,13 +39,14 @@ public class InstrumentedClassWriter extends ClassWriter
|
||||||
* @param analysis
|
* @param analysis
|
||||||
*/
|
*/
|
||||||
public InstrumentedClassWriter(String xiClassName, ClassReader xiReader,
|
public InstrumentedClassWriter(String xiClassName, ClassReader xiReader,
|
||||||
ClassAnalysis xiAnalysis, boolean xiShouldInstrument)
|
ClassAnalysis xiAnalysis, boolean xiShouldInstrument, AgentSettings settings)
|
||||||
{
|
{
|
||||||
super(xiReader, COMPUTE_MAXS);
|
super(xiReader, COMPUTE_MAXS);
|
||||||
className = xiClassName;
|
className = xiClassName;
|
||||||
analysis = xiAnalysis;
|
analysis = xiAnalysis;
|
||||||
shouldInstrument = xiShouldInstrument;
|
shouldInstrument = xiShouldInstrument;
|
||||||
threadClass = xiClassName.equals("java.lang.Thread");
|
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,
|
public MethodVisitor visitMethod(int access, String name, String desc,
|
||||||
String signature, String[] exceptions)
|
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,
|
MethodVisitor mv = super.visitMethod(access, name, desc, signature,
|
||||||
exceptions);
|
exceptions);
|
||||||
|
|
||||||
// Extract analysis results for this method
|
// If this class/method is not excluded, but then consider including it.
|
||||||
Set<Integer> branchTraceLines = analysis.methodReverseGOTOLines.get(name
|
// If all methods are allowed (by not specifying any methods) or this specific method is defined, then instrument it.
|
||||||
+ desc);
|
|
||||||
Integer entryLine = analysis.methodEntryLines.get(name + desc);
|
|
||||||
|
|
||||||
if (!threadClass || !name.equals("getUncaughtExceptionHandler"))
|
if (this.settings.getClassesToExclude()==null
|
||||||
{
|
||!this.settings.getClassesToExclude().thisMethodSpecified(this.className, name, desc)) {
|
||||||
mv = new InstrumentedMethodWriter(mv, access, name, desc,
|
if (this.settings.getClassesToInclude().thisMethodSpecified(this.className, name, desc) ) {
|
||||||
branchTraceLines, entryLine);
|
// 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
|
// Transform the method
|
||||||
return mv;
|
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.classRegex),
|
||||||
getListFromString(settingsData.classExcludeRegex),
|
getListFromString(settingsData.classExcludeRegex),
|
||||||
ALLOW_CLASSES);
|
ALLOW_ALL);
|
||||||
|
//ALLOW_CLASSES);
|
||||||
placeDialogInCenter(sWindow.getBounds(), regexInput.sWindow);
|
placeDialogInCenter(sWindow.getBounds(), regexInput.sWindow);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -2118,10 +2119,13 @@ public class InTraceUI implements ISocketCallback, IControlConnectionListener
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
settingsData.classRegex = includePattern;
|
String tmpInclude = includePattern.replace('[', '{');
|
||||||
settingsData.classExcludeRegex = excludePattern;
|
String tmpExclude = excludePattern.replace('[', '{');
|
||||||
controlThread.sendMessage(AgentConfigConstants.CLASS_REGEX + includePattern
|
|
||||||
+ AgentConfigConstants.EXCLUDE_CLASS_REGEX + excludePattern);
|
settingsData.classRegex = tmpInclude;
|
||||||
|
settingsData.classExcludeRegex = tmpExclude;
|
||||||
|
controlThread.sendMessage(AgentConfigConstants.CLASS_REGEX + tmpInclude
|
||||||
|
+ AgentConfigConstants.EXCLUDE_CLASS_REGEX + tmpExclude);
|
||||||
controlThread.sendMessage("getsettings");
|
controlThread.sendMessage("getsettings");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package org.intracetest.agent;
|
package org.intracetest.agent;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.intrace.agent.InstrCriteria;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
|
@ -9,6 +10,10 @@ import org.intrace.shared.AgentConfigConstants;
|
||||||
|
|
||||||
public class AgentSettingsTest extends TestCase
|
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()
|
public void testAgentSettings()
|
||||||
{
|
{
|
||||||
AgentSettings as = new AgentSettings(
|
AgentSettings as = new AgentSettings(
|
||||||
|
|
@ -22,8 +27,12 @@ public class AgentSettingsTest extends TestCase
|
||||||
+ "true");
|
+ "true");
|
||||||
assertNotNull(as.getClassRegex());
|
assertNotNull(as.getClassRegex());
|
||||||
assertEquals(as.getClassRegex().length, 2);
|
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.isInstrumentationEnabled(), true);
|
||||||
assertEquals(as.saveTracedClassfiles(), true);
|
assertEquals(as.saveTracedClassfiles(), true);
|
||||||
assertEquals(as.isVerboseMode(), true);
|
assertEquals(as.isVerboseMode(), true);
|
||||||
|
|
@ -31,8 +40,12 @@ public class AgentSettingsTest extends TestCase
|
||||||
as = new AgentSettings(as);
|
as = new AgentSettings(as);
|
||||||
assertNotNull(as.getClassRegex());
|
assertNotNull(as.getClassRegex());
|
||||||
assertEquals(as.getClassRegex().length, 2);
|
assertEquals(as.getClassRegex().length, 2);
|
||||||
assertEquals(as.getClassRegex()[0], "foo");
|
assertTrue( "foo".equals(as.getClassRegex()[0]) || "foo".equals(as.getClassRegex()[1]) );
|
||||||
assertEquals(as.getClassRegex()[1], "bar");
|
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.isInstrumentationEnabled(), true);
|
||||||
assertEquals(as.saveTracedClassfiles(), true);
|
assertEquals(as.saveTracedClassfiles(), true);
|
||||||
assertEquals(as.isVerboseMode(), true);
|
assertEquals(as.isVerboseMode(), true);
|
||||||
|
|
@ -41,11 +54,106 @@ public class AgentSettingsTest extends TestCase
|
||||||
assertNotNull(toString);
|
assertNotNull(toString);
|
||||||
|
|
||||||
Map<String, String> settingsMap = as.getSettingsMap();
|
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.INSTRU_ENABLED), "true");
|
||||||
assertEquals(settingsMap.get(AgentConfigConstants.SAVE_TRACED_CLASSFILES),
|
assertEquals(settingsMap.get(AgentConfigConstants.SAVE_TRACED_CLASSFILES),
|
||||||
"true");
|
"true");
|
||||||
assertEquals(settingsMap.get(AgentConfigConstants.VERBOSE_MODE), "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") );
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.easymock.IAnswer;
|
import org.easymock.IAnswer;
|
||||||
import org.easymock.classextension.EasyMock;
|
import org.easymock.EasyMock;
|
||||||
import org.intrace.output.AgentHelper;
|
import org.intrace.output.AgentHelper;
|
||||||
import org.intrace.output.IInstrumentationHandler;
|
import org.intrace.output.IInstrumentationHandler;
|
||||||
import org.intrace.shared.AgentConfigConstants;
|
import org.intrace.shared.AgentConfigConstants;
|
||||||
|
|
@ -229,8 +229,8 @@ public class AgentTest extends TestCase
|
||||||
// Setup agent
|
// Setup agent
|
||||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
||||||
testSetting(AgentConfigConstants.GZIP, "false");
|
testSetting(AgentConfigConstants.GZIP, "false");
|
||||||
testSetting(AgentConfigConstants.CLASS_REGEX, "BranchPatterns");
|
testSetting(AgentConfigConstants.CLASS_REGEX, "org.intracetest.agent.BranchPatterns");
|
||||||
testSetting(AgentConfigConstants.VERBOSE_MODE, "false");
|
testSetting(AgentConfigConstants.VERBOSE_MODE, "true");
|
||||||
testSetting(AgentConfigConstants.SAVE_TRACED_CLASSFILES, "true");
|
testSetting(AgentConfigConstants.SAVE_TRACED_CLASSFILES, "true");
|
||||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "true");
|
testSetting(AgentConfigConstants.INSTRU_ENABLED, "true");
|
||||||
|
|
||||||
|
|
@ -256,6 +256,8 @@ public class AgentTest extends TestCase
|
||||||
traceLine = capturedTrace.poll();
|
traceLine = capturedTrace.poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assertEquals(12,parsedTraceData.size());
|
||||||
|
|
||||||
// Verify the trace
|
// Verify the trace
|
||||||
assertNotNull(parsedTraceData.get("switchblock"));
|
assertNotNull(parsedTraceData.get("switchblock"));
|
||||||
{
|
{
|
||||||
|
|
@ -335,6 +337,7 @@ public class AgentTest extends TestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testArgumentTypes() throws Throwable
|
public void testArgumentTypes() throws Throwable
|
||||||
{
|
{
|
||||||
// Create and init the mock
|
// Create and init the mock
|
||||||
|
|
@ -345,7 +348,7 @@ public class AgentTest extends TestCase
|
||||||
// Setup agent
|
// Setup agent
|
||||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
testSetting(AgentConfigConstants.INSTRU_ENABLED, "false");
|
||||||
testSetting(AgentConfigConstants.GZIP, "false");
|
testSetting(AgentConfigConstants.GZIP, "false");
|
||||||
testSetting(AgentConfigConstants.CLASS_REGEX, "ArgumentTypes");
|
testSetting(AgentConfigConstants.CLASS_REGEX, "org.intracetest.agent.ArgumentTypes");
|
||||||
testSetting(AgentConfigConstants.VERBOSE_MODE, "false");
|
testSetting(AgentConfigConstants.VERBOSE_MODE, "false");
|
||||||
testSetting(AgentConfigConstants.SAVE_TRACED_CLASSFILES, "true");
|
testSetting(AgentConfigConstants.SAVE_TRACED_CLASSFILES, "true");
|
||||||
testSetting(AgentConfigConstants.INSTRU_ENABLED, "true");
|
testSetting(AgentConfigConstants.INSTRU_ENABLED, "true");
|
||||||
|
|
@ -510,7 +513,9 @@ public class AgentTest extends TestCase
|
||||||
private void parseLine(Map<String, TraceData> parsedTraceData,
|
private void parseLine(Map<String, TraceData> parsedTraceData,
|
||||||
String traceLine)
|
String traceLine)
|
||||||
{
|
{
|
||||||
System.out.println("Parse: " + traceLine);
|
//System.out.println("Parse: " + traceLine);
|
||||||
|
if (traceLine.contains("DEBUG"))
|
||||||
|
return;
|
||||||
String[] traceParts = traceLine.split(":##:");
|
String[] traceParts = traceLine.split(":##:");
|
||||||
String traceType = traceParts[0];
|
String traceType = traceParts[0];
|
||||||
String traceLineData = traceParts[1];
|
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)
|
private void byteArg(byte arg)
|
||||||
{
|
{
|
||||||
setProperty(Byte.toString(arg));
|
setProperty(Byte.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#byteArrayArg({B)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void byteArrayArg(byte[] arg)
|
private void byteArrayArg(byte[] arg)
|
||||||
{
|
{
|
||||||
setProperty(Arrays.toString(arg));
|
setProperty(Arrays.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#shortArg(S)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void shortArg(short arg)
|
private void shortArg(short arg)
|
||||||
{
|
{
|
||||||
setProperty(Short.toString(arg));
|
setProperty(Short.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#shortArrayArg({S)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void shortArrayArg(short[] arg)
|
private void shortArrayArg(short[] arg)
|
||||||
{
|
{
|
||||||
setProperty(Arrays.toString(arg));
|
setProperty(Arrays.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#intArg(I)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void intArg(int arg)
|
private void intArg(int arg)
|
||||||
{
|
{
|
||||||
setProperty(Integer.toString(arg));
|
setProperty(Integer.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#intArrayArg({I)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void intArrayArg(int[] arg)
|
private void intArrayArg(int[] arg)
|
||||||
{
|
{
|
||||||
setProperty(Arrays.toString(arg));
|
setProperty(Arrays.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#longArg(J)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void longArg(long arg)
|
private void longArg(long arg)
|
||||||
{
|
{
|
||||||
setProperty(Long.toString(arg));
|
setProperty(Long.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#longArrayArg({J)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void longArrayArg(long[] arg)
|
private void longArrayArg(long[] arg)
|
||||||
{
|
{
|
||||||
setProperty(Arrays.toString(arg));
|
setProperty(Arrays.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#floatArg(F)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void floatArg(float arg)
|
private void floatArg(float arg)
|
||||||
{
|
{
|
||||||
setProperty(Float.toString(arg));
|
setProperty(Float.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#floatArrayArg({F)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void floatArrayArg(float[] arg)
|
private void floatArrayArg(float[] arg)
|
||||||
{
|
{
|
||||||
setProperty(Arrays.toString(arg));
|
setProperty(Arrays.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#doubleArg(D)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void doubleArg(double arg)
|
private void doubleArg(double arg)
|
||||||
{
|
{
|
||||||
setProperty(Double.toString(arg));
|
setProperty(Double.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#doubleArrayArg({D)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void doubleArrayArg(double[] arg)
|
private void doubleArrayArg(double[] arg)
|
||||||
{
|
{
|
||||||
setProperty(Arrays.toString(arg));
|
setProperty(Arrays.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#boolArg(Z)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void boolArg(boolean arg)
|
private void boolArg(boolean arg)
|
||||||
{
|
{
|
||||||
setProperty(Boolean.toString(arg));
|
setProperty(Boolean.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#boolArrayArg({Z)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void boolArrayArg(boolean[] arg)
|
private void boolArrayArg(boolean[] arg)
|
||||||
{
|
{
|
||||||
setProperty(Arrays.toString(arg));
|
setProperty(Arrays.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#boolArrayArrayArg({{Z)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
private void boolArrayArrayArg(boolean[][] arg)
|
private void boolArrayArrayArg(boolean[][] arg)
|
||||||
{
|
{
|
||||||
setProperty(Arrays.toString(arg));
|
setProperty(Arrays.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#charArg(C)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void charArg(char arg)
|
private void charArg(char arg)
|
||||||
{
|
{
|
||||||
setProperty(Character.toString(arg));
|
setProperty(Character.toString(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#charArrayArg({C)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void charArrayArg(char[] arg)
|
private void charArrayArg(char[] arg)
|
||||||
{
|
{
|
||||||
setProperty(Arrays.toString(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)
|
private void objArg(Object arg)
|
||||||
{
|
{
|
||||||
setProperty(arg.toString());
|
setProperty(arg.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InTrace Method specifier syntax:
|
||||||
|
<pre>
|
||||||
|
org.intracetest.agent.ArgumentTypes#objArrayArg({Ljava/lang/Object;)V
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
|
||||||
private void objArrayArg(Object[] arg)
|
private void objArrayArg(Object[] arg)
|
||||||
{
|
{
|
||||||
setProperty(Arrays.toString(arg));
|
setProperty(Arrays.toString(arg));
|
||||||
|
|
@ -169,4 +301,20 @@ public class ArgumentTypes implements Runnable
|
||||||
{
|
{
|
||||||
System.setProperty("test-key", value);
|
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,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 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");
|
||||||
|
testSetting(AgentConfigConstants.GZIP, "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,388 @@
|
||||||
|
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");
|
||||||
|
testSetting(AgentConfigConstants.GZIP, "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