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