From a2a92d3814ade7c833a0a75fb5fe2a702ea1ce53 Mon Sep 17 00:00:00 2001 From: Martin Hare Robertson Date: Sat, 10 Apr 2010 17:27:19 +0100 Subject: [PATCH] Add support for capturing callers trace --- org.intrace/build.xml | 8 +- org.intrace/src/org/intrace/agent/Agent.java | 10 +- .../src/org/intrace/agent/AgentHelper.java | 123 ------- .../src/org/intrace/agent/AgentSettings.java | 35 +- .../org/intrace/agent/ClassTransformer.java | 52 +-- .../agent/InstrumentedMethodWriter.java | 2 +- .../agent/server/AgentClientConnection.java | 76 ++-- .../client/gui/CallersRegexInputWindow.java | 83 +++++ .../org/intrace/client/gui/ClientStrings.java | 17 +- .../client/gui/InstruRegexInputWindow.java | 84 +++++ .../org/intrace/client/gui/TraceWindow.java | 303 +++++++++++----- .../gui/helper/ControlConnectionThread.java | 20 +- .../gui/helper/NetworkDataReceiverThread.java | 71 ++++ .../client/gui/helper/ParsedSettingsData.java | 44 ++- .../src/org/intrace/output/AgentHelper.java | 343 ++++++++++++++++++ .../src/org/intrace/output/IOutput.java | 16 +- .../org/intrace/output/IOutputAdapter.java | 147 ++++++++ .../output/NetworkDataSenderThread.java | 85 +++++ .../org/intrace/output/OutputSettings.java | 124 +++++++ .../intrace/output/callers/CallersOutput.java | 79 ++++ .../output/callers/CallersSettings.java | 68 ++++ .../output/trace/TraceConfigConstants.java | 10 - .../org/intrace/output/trace/TraceOutput.java | 145 ++------ .../intrace/output/trace/TraceSettings.java | 108 +----- .../intrace/shared/AgentConfigConstants.java | 11 + .../shared/CallersConfigConstants.java | 8 + .../src/org/intrace/shared/CallersTree.java | 14 + .../intrace/shared/OutputConfigConstants.java | 7 + .../intrace/shared/TraceConfigConstants.java | 8 + 29 files changed, 1536 insertions(+), 565 deletions(-) delete mode 100644 org.intrace/src/org/intrace/agent/AgentHelper.java create mode 100644 org.intrace/src/org/intrace/client/gui/CallersRegexInputWindow.java create mode 100644 org.intrace/src/org/intrace/client/gui/InstruRegexInputWindow.java create mode 100644 org.intrace/src/org/intrace/client/gui/helper/NetworkDataReceiverThread.java create mode 100644 org.intrace/src/org/intrace/output/AgentHelper.java create mode 100644 org.intrace/src/org/intrace/output/IOutputAdapter.java create mode 100644 org.intrace/src/org/intrace/output/NetworkDataSenderThread.java create mode 100644 org.intrace/src/org/intrace/output/OutputSettings.java create mode 100644 org.intrace/src/org/intrace/output/callers/CallersOutput.java create mode 100644 org.intrace/src/org/intrace/output/callers/CallersSettings.java delete mode 100644 org.intrace/src/org/intrace/output/trace/TraceConfigConstants.java create mode 100644 org.intrace/src/org/intrace/shared/AgentConfigConstants.java create mode 100644 org.intrace/src/org/intrace/shared/CallersConfigConstants.java create mode 100644 org.intrace/src/org/intrace/shared/CallersTree.java create mode 100644 org.intrace/src/org/intrace/shared/OutputConfigConstants.java create mode 100644 org.intrace/src/org/intrace/shared/TraceConfigConstants.java diff --git a/org.intrace/build.xml b/org.intrace/build.xml index 5bc48c8..fec3436 100644 --- a/org.intrace/build.xml +++ b/org.intrace/build.xml @@ -49,9 +49,8 @@ - - - + + @@ -61,8 +60,7 @@ - - + diff --git a/org.intrace/src/org/intrace/agent/Agent.java b/org.intrace/src/org/intrace/agent/Agent.java index c2f0874..0922d08 100644 --- a/org.intrace/src/org/intrace/agent/Agent.java +++ b/org.intrace/src/org/intrace/agent/Agent.java @@ -5,6 +5,9 @@ import java.io.IOException; import java.lang.instrument.Instrumentation; import org.intrace.agent.server.AgentServer; +import org.intrace.output.AgentHelper; +import org.intrace.output.callers.CallersOutput; +import org.intrace.output.trace.TraceOutput; /** * Trace Agent: Installs a Class Transformer to add trace lines. @@ -43,8 +46,13 @@ public class Agent { System.out.println("Loaded Tracing Agent."); + if (agentArgs == null) agentArgs = ""; + + AgentHelper.outputHandlers.put(new TraceOutput(), new Object()); + AgentHelper.outputHandlers.put(new CallersOutput(), new Object()); + AgentSettings args = new AgentSettings(agentArgs); - AgentHelper.getActiveOutputHandler().getResponse(agentArgs); + AgentHelper.getResponses(agentArgs); ClassTransformer t = new ClassTransformer(inst, args); inst.addTransformer(t, true); diff --git a/org.intrace/src/org/intrace/agent/AgentHelper.java b/org.intrace/src/org/intrace/agent/AgentHelper.java deleted file mode 100644 index 3e69aa7..0000000 --- a/org.intrace/src/org/intrace/agent/AgentHelper.java +++ /dev/null @@ -1,123 +0,0 @@ -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 index d8495e0..4c1d5b2 100644 --- a/org.intrace/src/org/intrace/agent/AgentSettings.java +++ b/org.intrace/src/org/intrace/agent/AgentSettings.java @@ -4,26 +4,28 @@ import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; +import org.intrace.shared.AgentConfigConstants; + /** * Args Format: * "[arg1[arg2[arg3" - * + * * where argx is of the form * value-parameter */ public class AgentSettings { - private Pattern classRegex = Pattern.compile(""); + 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(); @@ -38,41 +40,41 @@ public class AgentSettings String[] seperateArgs = args.split("\\["); for (int ii = 0; ii < seperateArgs.length; ii++) { - parseArg(seperateArgs[ii].toLowerCase()); + parseArg(seperateArgs[ii]); } } - + private void parseArg(String arg) { - if (arg.equals("verbose-true")) + if (arg.toLowerCase().equals("verbose-true")) { verboseMode = true; } - else if (arg.equals("verbose-false")) + else if (arg.toLowerCase().equals("verbose-false")) { verboseMode = false; } - else if (arg.equals("instru-true")) + else if (arg.toLowerCase().equals("instru-true")) { tracingEnabled = true; } - else if (arg.equals("instru-false")) + else if (arg.toLowerCase().equals("instru-false")) { tracingEnabled = false; } - else if (arg.equals("saveinstru-true")) + else if (arg.toLowerCase().equals("saveinstru-true")) { saveTracedClassfiles = true; } - else if (arg.equals("saveinstru-false")) + else if (arg.toLowerCase().equals("saveinstru-false")) { saveTracedClassfiles = false; } - else if (arg.equals("instrujars-true")) + else if (arg.toLowerCase().equals("instrujars-true")) { allowJarsToBeTraced = true; } - else if (arg.equals("instrujars-false")) + else if (arg.toLowerCase().equals("instrujars-false")) { allowJarsToBeTraced = false; } @@ -107,7 +109,7 @@ public class AgentSettings { return allowJarsToBeTraced; } - + @Override public String toString() { @@ -118,10 +120,11 @@ public class AgentSettings currentSettings += "Trace Classes in JAR Files : " + allowJarsToBeTraced + "\n"; return currentSettings; } - + public Map getSettingsMap() { Map settingsMap = new HashMap(); + settingsMap.put(AgentConfigConstants.MAP_ID, AgentConfigConstants.MAP_ID); 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)); diff --git a/org.intrace/src/org/intrace/agent/ClassTransformer.java b/org.intrace/src/org/intrace/agent/ClassTransformer.java index 60e949a..73f66d2 100644 --- a/org.intrace/src/org/intrace/agent/ClassTransformer.java +++ b/org.intrace/src/org/intrace/agent/ClassTransformer.java @@ -9,10 +9,12 @@ import java.lang.instrument.Instrumentation; import java.lang.instrument.UnmodifiableClassException; import java.security.CodeSource; import java.security.ProtectionDomain; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentSkipListSet; +import org.intrace.output.AgentHelper; import org.objectweb.asm.ClassReader; /** @@ -24,9 +26,9 @@ public class ClassTransformer implements ClassFileTransformer * Map of modified class names to their original bytes */ private final Set modifiedClasses = - new ConcurrentSkipListSet(); + new ConcurrentSkipListSet(); private final Instrumentation inst; - private final AgentSettings args; + private final AgentSettings args; /** * cTor @@ -40,7 +42,7 @@ public class ClassTransformer implements ClassFileTransformer public ClassTransformer(Instrumentation xiInst, AgentSettings xiArgs) { inst = xiInst; - args = xiArgs; + args = xiArgs; if (args.isVerboseMode()) { System.out.println(args.toString()); @@ -94,7 +96,7 @@ public class ClassTransformer implements ClassFileTransformer } } else if (args.isTracingEnabled() && - isToBeConsideredForCoverage(loadedClass.getName(), loadedClass.getProtectionDomain())) + isToBeConsideredForCoverage(loadedClass.getName(), loadedClass.getProtectionDomain())) { try { @@ -145,7 +147,7 @@ public class ClassTransformer implements ClassFileTransformer } return false; } - + // Don't modify a class which is already modified if (modifiedClasses.contains(className)) { @@ -181,9 +183,9 @@ public class ClassTransformer implements ClassFileTransformer // 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.allowJarsToBeTraced() && + (codeSource != null) && + codeSource.getLocation().getPath().endsWith(".jar")) { if (args.isVerboseMode()) { @@ -191,7 +193,7 @@ public class ClassTransformer implements ClassFileTransformer } return false; } - return true; + return true; } @Override @@ -200,12 +202,12 @@ public class ClassTransformer implements ClassFileTransformer Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] originalClassfile) - throws IllegalClassFormatException + throws IllegalClassFormatException { String className = internalClassName.replace('/', '.'); if (args.isTracingEnabled() && isToBeConsideredForCoverage(className, protectionDomain)) - { + { if (args.isVerboseMode()) { System.out.println("!! Instrumenting class: " + className); @@ -233,7 +235,7 @@ public class ClassTransformer implements ClassFileTransformer else { System.out.println("Can't create directory " + parentDir + - " for saving traced classfiles."); + " for saving traced classfiles."); } } catch (Exception e) @@ -241,7 +243,7 @@ public class ClassTransformer implements ClassFileTransformer e.printStackTrace(); } } - + modifiedClasses.add(className); return newBytes; } @@ -255,21 +257,21 @@ public class ClassTransformer implements ClassFileTransformer 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(); + 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) + public List getResponse(String message) { AgentSettings oldSettings = new AgentSettings(args); args.parseArgs(message); - + if (args.isVerboseMode() && (oldSettings.isVerboseMode() != args.isVerboseMode())) { @@ -298,8 +300,8 @@ public class ClassTransformer implements ClassFileTransformer recheckModifiedClasses(); traceLoadedClasses(); } - - return AgentHelper.getActiveOutputHandler().getResponse(message); + + return AgentHelper.getResponses(message); } public Map getSettings() diff --git a/org.intrace/src/org/intrace/agent/InstrumentedMethodWriter.java b/org.intrace/src/org/intrace/agent/InstrumentedMethodWriter.java index d6575cc..030d950 100644 --- a/org.intrace/src/org/intrace/agent/InstrumentedMethodWriter.java +++ b/org.intrace/src/org/intrace/agent/InstrumentedMethodWriter.java @@ -16,7 +16,7 @@ import org.objectweb.asm.Type; */ public class InstrumentedMethodWriter extends MethodAdapter { - private static final String HELPER_CLASS = "org/intrace/agent/AgentHelper"; + private static final String HELPER_CLASS = "org/intrace/output/AgentHelper"; private final String className; private final String methodName; private final String methodDescriptor; diff --git a/org.intrace/src/org/intrace/agent/server/AgentClientConnection.java b/org.intrace/src/org/intrace/agent/server/AgentClientConnection.java index c423421..b940244 100644 --- a/org.intrace/src/org/intrace/agent/server/AgentClientConnection.java +++ b/org.intrace/src/org/intrace/agent/server/AgentClientConnection.java @@ -8,10 +8,11 @@ import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.Socket; import java.util.HashMap; +import java.util.List; import java.util.Map; -import org.intrace.agent.AgentHelper; import org.intrace.agent.ClassTransformer; +import org.intrace.output.AgentHelper; /** * Server thread handling a single connected client. @@ -24,11 +25,11 @@ public class AgentClientConnection implements Runnable /** * cTor - * @param agentServer + * @param agentServer * @param xiConnectedClient * @param xiTransformer */ - public AgentClientConnection(AgentServer agentServer, + public AgentClientConnection(AgentServer agentServer, Socket xiConnectedClient, ClassTransformer xiTransformer) { @@ -42,50 +43,53 @@ public class AgentClientConnection implements Runnable @Override public void run() { - try + try + { + boolean quit = false; + while (!quit) { - boolean quit = false; - while (!quit) + try { - try + String message = receiveMessage(); + if (message.equals("getsettings")) { - String message = receiveMessage(); - if (message.equals("getsettings")) + Map settingsMap = new HashMap(); + settingsMap.putAll(transformer.getSettings()); + settingsMap.putAll(AgentHelper.getSettings()); + serverRef.broadcastMessage(this, settingsMap); + } + else + { + List responses = transformer.getResponse(message); + if (responses.size() > 0) { - Map settingsMap = new HashMap(); - settingsMap.putAll(transformer.getSettings()); - settingsMap.putAll(AgentHelper.getActiveOutputHandler().getSettingsMap()); - serverRef.broadcastMessage(this, settingsMap); - } - else - { - String response = transformer.getResponse(message); - if (response != null) + for (String response : responses) { sendMessage(response); } - else - { - sendMessage("OK"); - } + } + else + { + sendMessage("OK"); } } - catch (IOException e) - { - quit = true; - } } - System.out.println("Disconnected from: " + connectedClient.getPort()); - connectedClient.close(); - } - catch (IOException e1) - { - e1.printStackTrace(); - } - finally - { - serverRef.removeClientConnection(this); + catch (IOException e) + { + quit = true; + } } + System.out.println("Disconnected from: " + connectedClient.getPort()); + connectedClient.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + finally + { + serverRef.removeClientConnection(this); + } } private String receiveMessage() throws IOException diff --git a/org.intrace/src/org/intrace/client/gui/CallersRegexInputWindow.java b/org.intrace/src/org/intrace/client/gui/CallersRegexInputWindow.java new file mode 100644 index 0000000..1aa6dc0 --- /dev/null +++ b/org.intrace/src/org/intrace/client/gui/CallersRegexInputWindow.java @@ -0,0 +1,83 @@ +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 CallersRegexInputWindow +{ + 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 mainWindowRef = 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 Method Regex"); + sShell.setLayout(gridLayout); + sShell.setSize(new Point(326, 82)); + sShell.addShellListener(new org.eclipse.swt.events.ShellAdapter() + { + @Override + 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 Method Regex"); + setRegexButton.setLayoutData(gridData1); + setRegexButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter() + { + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent e) + { + mainWindowRef.setCallersRegex(regexInput.getText()); + sShell.close(); + } + }); + cancelButton = new Button(sShell, SWT.NONE); + cancelButton.setText("Cancel"); + cancelButton.setLayoutData(gridData2); + cancelButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter() + { + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent e) + { + sShell.close(); + } + }); + } + + public void open(TraceWindow instanceWindowRef, String initText) + { + createSShell(); + sShell.open(); + regexInput.setText(initText); + mainWindowRef = instanceWindowRef; + } +} diff --git a/org.intrace/src/org/intrace/client/gui/ClientStrings.java b/org.intrace/src/org/intrace/client/gui/ClientStrings.java index b0a0230..4b63a8f 100644 --- a/org.intrace/src/org/intrace/client/gui/ClientStrings.java +++ b/org.intrace/src/org/intrace/client/gui/ClientStrings.java @@ -11,16 +11,21 @@ public class ClientStrings public static final String DISABLE_SAVECLASSES = "Don't Save Classes"; public static final String ENABLE_VERBOSEMODE = "Enable Verbose Mode"; public static final String DISABLE_VERBOSEMODE = "Disable Verbose Mode"; + public static final String ENABLE_EE_TRACE = "Enable Entry/Exit Trace"; public static final String DISABLE_EE_TRACE = "Disable Entry/Exit Trace"; public static final String ENABLE_BRANCH_TRACE = "Enable Branch Trace"; public static final String DISABLE_BRANCH_TRACE = "Disable Branch Trace"; public static final String ENABLE_ARGS_TRACE = "Enable Args Trace"; public static final String DISABLE_ARGS_TRACE = "Disable Args Trace"; - public static final String ENABLE_STDOUT_TRACE = "Enable StdOut Trace"; - public static final String DISABLE_STDOUT_TRACE = "Disable StdOut Trace"; - public static final String ENABLE_FILE_TRACE = "Enable File Trace"; - public static final String DISABLE_FILE_TRACE = "Disable File Trace"; - public static final String ENABLE_NETWORK_TRACE = "Enable Network Trace"; - public static final String DISABLE_NETWORK_TRACE = "Disable Network Trace"; + + public static final String BEGIN_CAPTURE_CALLERS = "Begin Callers Capture"; + public static final String END_CAPTURE_CALLERS = "End Callers Capture"; + + public static final String ENABLE_STDOUT_OUTPUT = "Enable StdOut Output"; + public static final String DISABLE_STDOUT_OUTPUT = "Disable StdOut Output"; + public static final String ENABLE_FILE_OUTPUT = "Enable File Output"; + public static final String DISABLE_FILE_OUTPUT = "Disable File Output"; + public static final String ENABLE_NETWORK_OUTPUT = "Enable Network Output"; + public static final String DISABLE_NETWORK_OUTPUT = "Disable Network Output"; } diff --git a/org.intrace/src/org/intrace/client/gui/InstruRegexInputWindow.java b/org.intrace/src/org/intrace/client/gui/InstruRegexInputWindow.java new file mode 100644 index 0000000..b18b76e --- /dev/null +++ b/org.intrace/src/org/intrace/client/gui/InstruRegexInputWindow.java @@ -0,0 +1,84 @@ +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 InstruRegexInputWindow +{ + 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 mainWindowRef = 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() + { + @Override + 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() + { + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent e) + { + mainWindowRef.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() + { + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent e) + { + sShell.close(); + } + }); + } + + public void open(TraceWindow instanceWindowRef, String initText) + { + createSShell(); + sShell.open(); + regexInput.setText(initText); + mainWindowRef = instanceWindowRef; + } +} diff --git a/org.intrace/src/org/intrace/client/gui/TraceWindow.java b/org.intrace/src/org/intrace/client/gui/TraceWindow.java index bdd0d11..136a19a 100644 --- a/org.intrace/src/org/intrace/client/gui/TraceWindow.java +++ b/org.intrace/src/org/intrace/client/gui/TraceWindow.java @@ -6,6 +6,7 @@ import java.net.InetAddress; import java.net.Socket; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; @@ -17,33 +18,38 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; import org.intrace.client.gui.helper.ControlConnectionThread; -import org.intrace.client.gui.helper.NetworkTraceReceiverThread; +import org.intrace.client.gui.helper.NetworkDataReceiverThread; import org.intrace.client.gui.helper.ParsedSettingsData; +import org.intrace.shared.CallersConfigConstants; public class TraceWindow -{ +{ // Window refs - private TraceWindow traceDialogRef = this; - private NewConnectionWindow newConnectionDialogRef; - + private final TraceWindow traceDialogRef = this; + private final NewConnectionWindow newConnectionDialogRef; + // Network details - private InetAddress remoteAddress; + private final InetAddress remoteAddress; private boolean networkTraceEnabled = false; - + // Threads - private NetworkTraceReceiverThread networkTraceThread; - private final ControlConnectionThread controlThread; - + private NetworkDataReceiverThread networkTraceThread; + private final ControlConnectionThread controlThread; + // Settings private ParsedSettingsData settingsData = new ParsedSettingsData(new HashMap()); // @jve:decl-index=0: - + // UI Elements private Shell sShell = null; private Button toggleEntryExitButton = null; private Button disconnectButton = null; - private Text statusTextArea = null; + private Text statusTextArea = null; private Button toggleStdOutButton = null; private Button toggleBranchButton = null; private Button toggleArgsButton = null; @@ -59,13 +65,19 @@ public class TraceWindow private Button toggleVerboseMode = null; private Button toggleFileOutputButton = null; private Button toggleNetworkTraceButton = null; - + private TabFolder outputTabFolder = null; + private TabItem textOutputTabItem = null; + private TabItem callersOutputTabItem = null; + private Tree callersTree = null; + private Label callersLabel = null; + private Button callersStateButton = null; + public TraceWindow(NewConnectionWindow instanceRef, Socket socket) { this.newConnectionDialogRef = instanceRef; this.remoteAddress = socket.getInetAddress(); controlThread = new ControlConnectionThread(socket, this); - controlThread.start(); + controlThread.start(); } /** @@ -73,6 +85,8 @@ public class TraceWindow */ private void createSShell() { + GridData gridData12 = new GridData(); + gridData12.widthHint = 150; GridData gridData22 = new GridData(); gridData22.widthHint = 150; GridData gridData11 = new GridData(); @@ -111,21 +125,23 @@ public class TraceWindow toggleInstrumentEnabled.setText(ClientStrings.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"); - } - }); + .addMouseListener(new org.eclipse.swt.events.MouseAdapter() + { + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent e) + { + toggleSetting(settingsData.instrEnabled, "[instru-true", "[instru-false"); + } + }); setClassRegexButton = new Button(sShell, SWT.LEFT); setClassRegexButton.setText(ClientStrings.SET_CLASSREGEX); setClassRegexButton.setLayoutData(gridData41); setClassRegexButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter() { + @Override public void mouseUp(org.eclipse.swt.events.MouseEvent e) { - RegexInput regexInput = new RegexInput(); + InstruRegexInputWindow regexInput = new InstruRegexInputWindow(); regexInput.open(traceDialogRef, settingsData.classRegex); } }); @@ -134,6 +150,7 @@ public class TraceWindow toggleAllowJarInstru.setLayoutData(gridData5); toggleAllowJarInstru.addMouseListener(new org.eclipse.swt.events.MouseAdapter() { + @Override public void mouseUp(org.eclipse.swt.events.MouseEvent e) { toggleSetting(settingsData.allowJarsToBeTraced, "[instrujars-true", "[instrujars-false"); @@ -144,6 +161,7 @@ public class TraceWindow toggleSaveClassFiles.setLayoutData(gridData6); toggleSaveClassFiles.addMouseListener(new org.eclipse.swt.events.MouseAdapter() { + @Override public void mouseUp(org.eclipse.swt.events.MouseEvent e) { toggleSetting(settingsData.saveTracedClassfiles, "[saveinstru-true", "[saveinstru-false"); @@ -154,6 +172,7 @@ public class TraceWindow toggleVerboseMode.setLayoutData(gridData7); toggleVerboseMode.addMouseListener(new org.eclipse.swt.events.MouseAdapter() { + @Override public void mouseUp(org.eclipse.swt.events.MouseEvent e) { toggleSetting(settingsData.verboseMode, "[verbose-true", "[verbose-false"); @@ -164,6 +183,7 @@ public class TraceWindow traceSettingsLabel.setText("Trace Settings:"); sShell.addShellListener(new org.eclipse.swt.events.ShellAdapter() { + @Override public void shellClosed(org.eclipse.swt.events.ShellEvent e) { disconnect(); @@ -175,18 +195,20 @@ public class TraceWindow toggleEntryExitButton.setText(ClientStrings.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"); - } - }); + .addMouseListener(new org.eclipse.swt.events.MouseAdapter() + { + @Override + 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(ClientStrings.ENABLE_BRANCH_TRACE); toggleBranchButton.setLayoutData(gridData1); toggleBranchButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter() { + @Override public void mouseUp(org.eclipse.swt.events.MouseEvent e) { toggleSetting(settingsData.branchEnabled, "[trace-branch-true", "[trace-branch-false"); @@ -195,47 +217,72 @@ public class TraceWindow toggleArgsButton = new Button(sShell, SWT.LEFT); toggleArgsButton.setText(ClientStrings.ENABLE_ARGS_TRACE); toggleArgsButton.setLayoutData(gridData21); + callersLabel = new Label(sShell, SWT.NONE); + callersLabel.setText("Callers Settings:"); + callersStateButton = new Button(sShell, SWT.NONE); + callersStateButton.setLayoutData(gridData12); + callersStateButton.setText(ClientStrings.BEGIN_CAPTURE_CALLERS); + callersStateButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter() + { + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent e) + { + if (!settingsData.callersCaptureInProgress) + { + CallersRegexInputWindow regexInput = new CallersRegexInputWindow(); + regexInput.open(traceDialogRef, settingsData.callersRegex); + } + else + { + toggleSetting(settingsData.callersCaptureInProgress, "[callers-enabled-true", "[callers-enabled-false"); + } + } + }); outputSettingsLabel = new Label(sShell, SWT.NONE); outputSettingsLabel.setText("Output Modes:"); toggleArgsButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter() { + @Override 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(ClientStrings.ENABLE_STDOUT_TRACE); + toggleStdOutButton.setText(ClientStrings.ENABLE_STDOUT_OUTPUT); toggleStdOutButton.setLayoutData(gridData4); toggleFileOutputButton = new Button(sShell, SWT.LEFT); - toggleFileOutputButton.setText(ClientStrings.ENABLE_FILE_TRACE); + toggleFileOutputButton.setText(ClientStrings.ENABLE_FILE_OUTPUT); toggleFileOutputButton.setLayoutData(gridData11); toggleNetworkTraceButton = new Button(sShell, SWT.LEFT); - toggleNetworkTraceButton.setText(ClientStrings.ENABLE_NETWORK_TRACE); + toggleNetworkTraceButton.setText(ClientStrings.ENABLE_NETWORK_OUTPUT); toggleNetworkTraceButton.setLayoutData(gridData22); toggleNetworkTraceButton - .addMouseListener(new org.eclipse.swt.events.MouseAdapter() - { - public void mouseUp(org.eclipse.swt.events.MouseEvent e) - { - toggleNetworkTrace(); - } - }); + .addMouseListener(new org.eclipse.swt.events.MouseAdapter() + { + @Override + 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"); - } - }); + .addMouseListener(new org.eclipse.swt.events.MouseAdapter() + { + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent e) + { + toggleSetting(settingsData.fileOutEnabled, "[out-file-true", "[out-file-false"); + } + }); spacerLabel = new Label(sShell, SWT.NONE); spacerLabel.setText(""); toggleStdOutButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter() { + @Override public void mouseUp(org.eclipse.swt.events.MouseEvent e) { - toggleSetting(settingsData.stdOutEnabled, "[trace-stdout-true", "[trace-stdout-false"); + toggleSetting(settingsData.stdOutEnabled, "[out-stdout-true", "[out-stdout-false"); } }); disconnectButton = new Button(sShell, SWT.LEFT); @@ -243,6 +290,7 @@ public class TraceWindow disconnectButton.setLayoutData(gridData); disconnectButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter() { + @Override public void mouseUp(org.eclipse.swt.events.MouseEvent e) { sShell.close(); @@ -251,7 +299,7 @@ public class TraceWindow } /** - * This method initializes composite + * This method initializes composite * */ private void createComposite() @@ -262,14 +310,12 @@ public class TraceWindow gridData3.grabExcessVerticalSpace = true; gridData3.heightHint = 99999; gridData3.widthHint = 99999; - gridData3.verticalSpan = 17; + gridData3.verticalSpan = 19; 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)); + createOutputTabFolder(); } public void open() @@ -277,9 +323,9 @@ public class TraceWindow createSShell(); sShell.open(); addMessage("*** Connected!"); - controlThread.sendMessage("getsettings"); + controlThread.sendMessage("getsettings"); } - + public void disconnect() { controlThread.disconnect(); @@ -288,63 +334,63 @@ public class TraceWindow networkTraceThread.disconnect(); } } - + private void toggleNetworkTrace() { sShell.getDisplay().asyncExec(new Runnable() - { + { @Override public void run() { disableButtons(); if (!networkTraceEnabled) { - controlThread.sendMessage("[trace-network"); + controlThread.sendMessage("[out-network"); String networkTracePortStr = controlThread.getMessage(); int networkTracePort = Integer.parseInt(networkTracePortStr); try - { - networkTraceThread = new NetworkTraceReceiverThread(remoteAddress, networkTracePort, traceDialogRef); + { + networkTraceThread = new NetworkDataReceiverThread(remoteAddress, networkTracePort, traceDialogRef); networkTraceThread.start(); networkTraceEnabled = true; } catch (IOException ex) { addMessage("*** Failed to setup network trace: " + ex.toString()); - } + } } else { networkTraceThread.disconnect(); networkTraceEnabled = false; - } - updateButtonText(); + } + updateButtonText(); } }); } - + public void setRegex(final String regex) { sShell.getDisplay().asyncExec(new Runnable() - { + { @Override public void run() { - disableButtons(); - controlThread.sendMessage("[regex-" + regex); - controlThread.sendMessage("getsettings"); + disableButtons(); + controlThread.sendMessage("[regex-" + regex); + controlThread.sendMessage("getsettings"); } }); - } - + } + private void toggleSetting(final boolean settingValue, final String enableCommand, final String disableCommand) { sShell.getDisplay().asyncExec(new Runnable() - { + { @Override public void run() { - disableButtons(); + disableButtons(); if (settingValue) { controlThread.sendMessage(disableCommand); @@ -353,11 +399,11 @@ public class TraceWindow { controlThread.sendMessage(enableCommand); } - controlThread.sendMessage("getsettings"); + controlThread.sendMessage("getsettings"); } - }); + }); } - + private void disableButtons() { toggleInstrumentEnabled.setEnabled(false); @@ -365,14 +411,18 @@ public class TraceWindow toggleAllowJarInstru.setEnabled(false); toggleSaveClassFiles.setEnabled(false); toggleVerboseMode.setEnabled(false); + toggleEntryExitButton.setEnabled(false); toggleBranchButton.setEnabled(false); toggleArgsButton.setEnabled(false); + + callersStateButton.setEnabled(false); + toggleStdOutButton.setEnabled(false); toggleFileOutputButton.setEnabled(false); toggleNetworkTraceButton.setEnabled(false); } - + private void chooseText(Button control, boolean option, String enabledText, String disabledText) { if (option) @@ -385,47 +435,122 @@ public class TraceWindow } control.setEnabled(true); } - + private void updateButtonText() { addMessage("*** Latest Settings Received"); - + chooseText(toggleInstrumentEnabled, settingsData.instrEnabled, ClientStrings.ENABLE_INSTR, ClientStrings.DISABLE_INSTR); chooseText(toggleAllowJarInstru, settingsData.allowJarsToBeTraced, ClientStrings.ENABLE_ALLOWJARS, ClientStrings.DISABLE_ALLOWJARS); chooseText(toggleSaveClassFiles, settingsData.saveTracedClassfiles, ClientStrings.ENABLE_SAVECLASSES, ClientStrings.DISABLE_SAVECLASSES); chooseText(toggleVerboseMode, settingsData.verboseMode, ClientStrings.ENABLE_VERBOSEMODE, ClientStrings.DISABLE_VERBOSEMODE); + chooseText(toggleEntryExitButton, settingsData.entryExitEnabled, ClientStrings.ENABLE_EE_TRACE, ClientStrings.DISABLE_EE_TRACE); chooseText(toggleBranchButton, settingsData.branchEnabled, ClientStrings.ENABLE_BRANCH_TRACE, ClientStrings.DISABLE_BRANCH_TRACE); chooseText(toggleArgsButton, settingsData.argsEnabled, ClientStrings.ENABLE_ARGS_TRACE, ClientStrings.DISABLE_ARGS_TRACE); - chooseText(toggleStdOutButton, settingsData.stdOutEnabled, ClientStrings.ENABLE_STDOUT_TRACE, ClientStrings.DISABLE_STDOUT_TRACE); - chooseText(toggleFileOutputButton, settingsData.fileOutEnabled, ClientStrings.ENABLE_FILE_TRACE, ClientStrings.DISABLE_FILE_TRACE); - chooseText(toggleNetworkTraceButton, networkTraceEnabled, ClientStrings.ENABLE_NETWORK_TRACE, ClientStrings.DISABLE_NETWORK_TRACE); + + chooseText(callersStateButton, settingsData.callersCaptureInProgress, ClientStrings.BEGIN_CAPTURE_CALLERS, ClientStrings.END_CAPTURE_CALLERS); + + chooseText(toggleStdOutButton, settingsData.stdOutEnabled, ClientStrings.ENABLE_STDOUT_OUTPUT, ClientStrings.DISABLE_STDOUT_OUTPUT); + chooseText(toggleFileOutputButton, settingsData.fileOutEnabled, ClientStrings.ENABLE_FILE_OUTPUT, ClientStrings.DISABLE_FILE_OUTPUT); + chooseText(toggleNetworkTraceButton, networkTraceEnabled, ClientStrings.ENABLE_NETWORK_OUTPUT, ClientStrings.DISABLE_NETWORK_OUTPUT); setClassRegexButton.setEnabled(true); - } - + } + public void setConfig(final Map settingsMap) { sShell.getDisplay().asyncExec(new Runnable() - { + { @Override public void run() { addMessage("*** Fetch Settings"); settingsData = new ParsedSettingsData(settingsMap); - updateButtonText(); + updateButtonText(); } - }); + }); } - + public void addMessage(final String message) { sShell.getDisplay().asyncExec(new Runnable() - { + { @Override public void run() { - statusTextArea.append(message + "\n"); + statusTextArea.append(message + "\n"); } - }); + }); + } + + /** + * This method initializes outputTabFolder + * + */ + private void createOutputTabFolder() + { + outputTabFolder = new TabFolder(composite, SWT.NONE); + statusTextArea = new Text(outputTabFolder, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER); + statusTextArea.setEditable(false); + statusTextArea.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE)); + callersTree = new Tree(outputTabFolder, SWT.BORDER); + + textOutputTabItem = new TabItem(outputTabFolder, SWT.NONE); + textOutputTabItem.setControl(statusTextArea); + textOutputTabItem.setText("Text Output"); + callersOutputTabItem = new TabItem(outputTabFolder, SWT.NONE); + callersOutputTabItem.setControl(callersTree); + callersOutputTabItem.setText("Callers"); + } + + public void setCallers(final Map callersMap) + { + callersMap.remove(CallersConfigConstants.MAP_ID); + sShell.getDisplay().asyncExec(new Runnable() + { + @Override + public void run() + { + callersTree.removeAll(); + addCallersData(callersTree, callersMap); + } + }); + } + + @SuppressWarnings("unchecked") + private void addCallersData(Object parentItem, Map callersMap) + { + for (Entry mapEntry : callersMap.entrySet()) + { + String entryName = mapEntry.getKey(); + TreeItem item; + if (parentItem instanceof Tree) + { + item = new TreeItem((Tree)parentItem, SWT.NULL); + } + else + { + item = new TreeItem((TreeItem)parentItem, SWT.NULL); + } + item.setText(entryName); + Object entryValue = mapEntry.getValue(); + if (entryValue instanceof Map) + { + Map entryMap = (Map)entryValue; + if (entryMap.size() > 0) + { + addCallersData(item, entryMap); + } + } + } + } + + public void setCallersRegex(String regex) + { + if (!settingsData.callersCaptureInProgress) + { + controlThread.sendMessage("[callers-regex-" + regex); + toggleSetting(settingsData.callersCaptureInProgress, "[callers-enabled-true", "[callers-enabled-false"); + } } } diff --git a/org.intrace/src/org/intrace/client/gui/helper/ControlConnectionThread.java b/org.intrace/src/org/intrace/client/gui/helper/ControlConnectionThread.java index 46a70fd..db8b8e5 100644 --- a/org.intrace/src/org/intrace/client/gui/helper/ControlConnectionThread.java +++ b/org.intrace/src/org/intrace/client/gui/helper/ControlConnectionThread.java @@ -19,7 +19,7 @@ public class ControlConnectionThread implements Runnable private final BlockingQueue outgoingMessages = new LinkedBlockingQueue(); private final ControlConnectionSenderThread senderThread = new ControlConnectionSenderThread(); private Thread sendThread; - + public ControlConnectionThread(Socket socket, TraceWindow window) { this.window = window; @@ -32,13 +32,13 @@ public class ControlConnectionThread implements Runnable receiveThread.setDaemon(true); receiveThread.setName("Control Receive Thread"); receiveThread.start(); - + sendThread = new Thread(senderThread); sendThread.setDaemon(true); sendThread.setName("Control Sender Thread"); sendThread.start(); } - + public String getMessage() { try @@ -56,11 +56,11 @@ public class ControlConnectionThread implements Runnable public void run() { try - { + { while (true) { ObjectInputStream objIn = new ObjectInputStream(socket.getInputStream()); - Object receivedMessage = (Object)objIn.readObject(); + Object receivedMessage = objIn.readObject(); if (receivedMessage instanceof Map) { Map settingsMap = (Map)receivedMessage; @@ -78,10 +78,10 @@ public class ControlConnectionThread implements Runnable } catch (Exception e) { - window.disconnect(); + window.disconnect(); } } - + public void disconnect() { if (sendThread != null) @@ -107,11 +107,11 @@ public class ControlConnectionThread implements Runnable catch (InterruptedException e1) { // Throw away - } + } } - + private class ControlConnectionSenderThread implements Runnable - { + { @Override public void run() { diff --git a/org.intrace/src/org/intrace/client/gui/helper/NetworkDataReceiverThread.java b/org.intrace/src/org/intrace/client/gui/helper/NetworkDataReceiverThread.java new file mode 100644 index 0000000..e8b5d87 --- /dev/null +++ b/org.intrace/src/org/intrace/client/gui/helper/NetworkDataReceiverThread.java @@ -0,0 +1,71 @@ +package org.intrace.client.gui.helper; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.Map; + +import org.intrace.client.gui.TraceWindow; + +public class NetworkDataReceiverThread implements Runnable +{ + private final Socket traceSocket; + private final TraceWindow window; + public NetworkDataReceiverThread(InetAddress address, int networkTracePort, TraceWindow window) throws IOException + { + this.window = window; + traceSocket = new Socket(); + traceSocket.connect(new InetSocketAddress(address, networkTracePort)); + } + + public void start() + { + Thread t = new Thread(this); + t.setDaemon(true); + t.setName("Network Data Receiver"); + t.start(); + } + + @SuppressWarnings("unchecked") + @Override + public void run() + { + try + { + ObjectInputStream objIn = new ObjectInputStream(traceSocket.getInputStream()); + while (true) + { + Object data = objIn.readObject(); + if (data instanceof String) + { + String traceLine = (String)data; + window.addMessage(traceLine); + } + else if (data instanceof Map) + { + Map callersMap = (Map)data; + window.setCallers(callersMap); + } + } + } + catch (Exception e) + { + disconnect(); + } + } + + public void disconnect() + { + try + { + traceSocket.close(); + } + catch (IOException e) + { + // Do nothing + } + } + +} diff --git a/org.intrace/src/org/intrace/client/gui/helper/ParsedSettingsData.java b/org.intrace/src/org/intrace/client/gui/helper/ParsedSettingsData.java index 5b3ca91..d16e762 100644 --- a/org.intrace/src/org/intrace/client/gui/helper/ParsedSettingsData.java +++ b/org.intrace/src/org/intrace/client/gui/helper/ParsedSettingsData.java @@ -3,8 +3,10 @@ package org.intrace.client.gui.helper; import java.util.Map; -import org.intrace.agent.AgentConfigConstants; -import org.intrace.output.trace.TraceConfigConstants; +import org.intrace.shared.AgentConfigConstants; +import org.intrace.shared.CallersConfigConstants; +import org.intrace.shared.OutputConfigConstants; +import org.intrace.shared.TraceConfigConstants; public class ParsedSettingsData { @@ -13,16 +15,19 @@ public class ParsedSettingsData public final boolean saveTracedClassfiles; public final boolean verboseMode; public final boolean allowJarsToBeTraced; - + + public final boolean callersCaptureInProgress; + public final boolean entryExitEnabled; public final boolean branchEnabled; public final boolean argsEnabled; public final boolean stdOutEnabled; public final boolean fileOutEnabled; + public final String callersRegex; public ParsedSettingsData(Map settingsMap) { classRegex = settingsMap.get(AgentConfigConstants.CLASS_REGEX); - + if ("true".equals(settingsMap.get(AgentConfigConstants.TRACING_ENABLED))) { instrEnabled = true; @@ -31,7 +36,7 @@ public class ParsedSettingsData { instrEnabled = false; } - + if ("true".equals(settingsMap.get(AgentConfigConstants.SAVE_TRACED_CLASSFILES))) { saveTracedClassfiles = true; @@ -40,7 +45,7 @@ public class ParsedSettingsData { saveTracedClassfiles = false; } - + if ("true".equals(settingsMap.get(AgentConfigConstants.VERBOSE_MODE))) { verboseMode = true; @@ -49,7 +54,7 @@ public class ParsedSettingsData { verboseMode = false; } - + if ("true".equals(settingsMap.get(AgentConfigConstants.ALLOW_JARS_TO_BE_TRACED))) { allowJarsToBeTraced = true; @@ -58,7 +63,18 @@ public class ParsedSettingsData { allowJarsToBeTraced = false; } - + + callersRegex = settingsMap.get(CallersConfigConstants.PATTERN); + + if ("true".equals(settingsMap.get(CallersConfigConstants.CALLERS_ENABLED))) + { + callersCaptureInProgress = true; + } + else + { + callersCaptureInProgress = false; + } + if ("true".equals(settingsMap.get(TraceConfigConstants.ENTRY_EXIT))) { entryExitEnabled = true; @@ -67,7 +83,7 @@ public class ParsedSettingsData { entryExitEnabled = false; } - + if ("true".equals(settingsMap.get(TraceConfigConstants.BRANCH))) { branchEnabled = true; @@ -76,7 +92,7 @@ public class ParsedSettingsData { branchEnabled = false; } - + if ("true".equals(settingsMap.get(TraceConfigConstants.ARG))) { argsEnabled = true; @@ -85,8 +101,8 @@ public class ParsedSettingsData { argsEnabled = false; } - - if ("true".equals(settingsMap.get(TraceConfigConstants.STD_OUT))) + + if ("true".equals(settingsMap.get(OutputConfigConstants.STD_OUT))) { stdOutEnabled = true; } @@ -94,8 +110,8 @@ public class ParsedSettingsData { stdOutEnabled = false; } - - if ("true".equals(settingsMap.get(TraceConfigConstants.FILE_OUT))) + + if ("true".equals(settingsMap.get(OutputConfigConstants.FILE_OUT))) { fileOutEnabled = true; } diff --git a/org.intrace/src/org/intrace/output/AgentHelper.java b/org.intrace/src/org/intrace/output/AgentHelper.java new file mode 100644 index 0000000..51b6903 --- /dev/null +++ b/org.intrace/src/org/intrace/output/AgentHelper.java @@ -0,0 +1,343 @@ +package org.intrace.output; + +import java.io.IOException; +import java.io.PrintWriter; +import java.net.ServerSocket; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + + + +/** + * Static implementation of the TraceWriter interface + */ +public class AgentHelper +{ + public static final Map outputHandlers = new ConcurrentHashMap(); + + private static OutputSettings outputSettings = new OutputSettings(""); + private static boolean file1Active = true; + private static int writtenChars = 0; + private static final int MAX_CHARS_PER_FILE = 100 * 1000; // 100kb + + private static final Map networkOutputThreads = new ConcurrentHashMap(); + + public static List getResponses(String agentArgs) + { + List responses = new ArrayList(); + String response = getResponse(agentArgs); + if (response != null) + { + responses.add(response); + } + for (IOutput outputHandler : outputHandlers.keySet()) + { + response = outputHandler.getResponse(agentArgs); + if (response != null) + { + responses.add(response); + } + } + return responses; + } + + private static String getResponse(String args) + { + boolean oldStdOutEnabled = outputSettings.isStdoutTraceOutputEnabled(); + boolean oldFileOutEnabled = outputSettings.isFileTraceOutputEnabled(); + outputSettings.parseArgs(args); + + if ((oldStdOutEnabled != outputSettings.isStdoutTraceOutputEnabled()) || + (oldFileOutEnabled != outputSettings.isFileTraceOutputEnabled())) + { + System.out.println("## Output Settings Changed"); + } + + if (outputSettings.networkTraceOutputRequested) + { + System.out.println("## Network Output Requested"); + ServerSocket networkSocket; + try + { + networkSocket = new ServerSocket(0); + NetworkDataSenderThread networkOutputThread = new NetworkDataSenderThread(networkSocket); + + networkOutputThreads.put(networkOutputThread, new Object()); + + networkOutputThread.start(networkOutputThreads.keySet()); + outputSettings.networkTraceOutputRequested = false; + return Integer.toString(networkSocket.getLocalPort()); + } + catch (IOException e) + { + // Do nothing + return null; + } + } + else + { + return null; + } + } + + public static Map getSettings() + { + Map settings = new HashMap(); + settings.putAll(outputSettings.getSettingsMap()); + for (IOutput outputHandler : outputHandlers.keySet()) + { + settings.putAll(outputHandler.getSettingsMap()); + } + return settings; + } + + /** + * Write output + * + * @param xiTrace + */ + public static void writeOutput(String xiOutput) + { + SimpleDateFormat dateFormat = new SimpleDateFormat(); + long threadID = Thread.currentThread().getId(); + String traceString = "[" + dateFormat.format(new Date()) + "]:[" + + threadID + "]:" + xiOutput; + if (outputSettings.isStdoutTraceOutputEnabled()) + { + System.out.println(traceString); + } + + if (outputSettings.isFileTraceOutputEnabled()) + { + writeFileTrace(traceString); + } + + Set networkThreads = networkOutputThreads.keySet(); + if (networkThreads.size() > 0) + { + for (NetworkDataSenderThread thread : networkThreads) + { + thread.queueData(traceString); + } + } + } + + /** + * Write data output + * + * @param xiTrace + */ + public static void writeDataOutput(Object xiOutput) + { + Set networkThreads = networkOutputThreads.keySet(); + if (networkThreads.size() > 0) + { + for (NetworkDataSenderThread thread : networkThreads) + { + thread.queueData(xiOutput); + } + } + } + + private static synchronized void writeFileTrace(String traceString) + { + PrintWriter outputWriter; + if (file1Active) + { + outputWriter = outputSettings.getFile1TraceWriter(); + } + else + { + outputWriter = outputSettings.getFile2TraceWriter(); + } + outputWriter.println(traceString); + outputWriter.flush(); + + // Switch trace files if necessary + writtenChars += traceString.length(); + if (writtenChars > MAX_CHARS_PER_FILE) + { + writtenChars = 0; + outputSettings.resetTraceFiles(file1Active, !file1Active); + file1Active = !file1Active; + } + } + + /* + * STATIC IMPLEMENTATION OF IOutput + */ + + public static void enter(String className, String methodName) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.enter(className, methodName); + } + } + + public static void arg(String className, String methodName, byte byteArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, byteArg); + } + } + + public static void arg(String className, String methodName, byte[] byteArrayArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, byteArrayArg); + } + } + + public static void arg(String className, String methodName, short shortArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, shortArg); + } + } + + public static void arg(String className, String methodName, short[] shortArrayArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, shortArrayArg); + } + } + + public static void arg(String className, String methodName, int intArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, intArg); + } + } + + public static void arg(String className, String methodName, int[] intArrayArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, intArrayArg); + } + } + + public static void arg(String className, String methodName, long longArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, longArg); + } + } + + public static void arg(String className, String methodName, long[] longArrayArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, longArrayArg); + } + } + + public static void arg(String className, String methodName, float floatArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, floatArg); + } + } + + public static void arg(String className, String methodName, float[] floatArrayArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, floatArrayArg); + } + } + + public static void arg(String className, String methodName, double doubleArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, doubleArg); + } + } + + public static void arg(String className, String methodName, double[] doubleArrayArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, doubleArrayArg); + } + } + + public static void arg(String className, String methodName, boolean boolArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, boolArg); + } + } + + public static void arg(String className, String methodName, boolean[] boolArrayArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, boolArrayArg); + } + } + + public static void arg(String className, String methodName, char charArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, charArg); + } + } + + public static void arg(String className, String methodName, char[] charArrayArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, charArrayArg); + } + } + + public static void arg(String className, String methodName, Object objArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, objArg); + } + } + + public static void arg(String className, String methodName, Object[] objArrayArg) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.arg(className, methodName, objArrayArg); + } + } + + public static void branch(String className, String methodName, int lineNo) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.branch(className, methodName, lineNo); + } + } + + public static void exit(String className, String methodName, int lineNo) + { + for (IOutput outputHandler : outputHandlers.keySet()) + { + outputHandler.exit(className, methodName, lineNo); + } + } +} diff --git a/org.intrace/src/org/intrace/output/IOutput.java b/org.intrace/src/org/intrace/output/IOutput.java index fa5be68..fc251ad 100644 --- a/org.intrace/src/org/intrace/output/IOutput.java +++ b/org.intrace/src/org/intrace/output/IOutput.java @@ -8,33 +8,33 @@ import java.util.Map; 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 String getResponse(String args); public Map getSettingsMap(); } diff --git a/org.intrace/src/org/intrace/output/IOutputAdapter.java b/org.intrace/src/org/intrace/output/IOutputAdapter.java new file mode 100644 index 0000000..4baed2f --- /dev/null +++ b/org.intrace/src/org/intrace/output/IOutputAdapter.java @@ -0,0 +1,147 @@ +package org.intrace.output; + +import java.util.HashMap; +import java.util.Map; + +public class IOutputAdapter implements IOutput +{ + + @Override + public void arg(String className, String methodName, byte byteArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, byte[] byteArrayArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, short shortArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, short[] shortArrayArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, int intArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, int[] intArrayArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, long longArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, long[] longArrayArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, float floatArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, float[] floatArrayArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, double doubleArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, double[] doubleArrayArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, boolean boolArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, boolean[] boolArrayArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, char charArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, char[] charArrayArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, Object objArg) + { + // Do nothing + } + + @Override + public void arg(String className, String methodName, Object[] objArrayArg) + { + // Do nothing + } + + @Override + public void branch(String className, String methodName, int lineNo) + { + // Do nothing + } + + @Override + public void enter(String className, String methodName) + { + // Do nothing + } + + @Override + public void exit(String className, String methodName, int lineNo) + { + // Do nothing + } + + @Override + public String getResponse(String args) + { + // Do nothing + return null; + } + + @Override + public Map getSettingsMap() + { + return new HashMap(); + } +} diff --git a/org.intrace/src/org/intrace/output/NetworkDataSenderThread.java b/org.intrace/src/org/intrace/output/NetworkDataSenderThread.java new file mode 100644 index 0000000..e8c27bc --- /dev/null +++ b/org.intrace/src/org/intrace/output/NetworkDataSenderThread.java @@ -0,0 +1,85 @@ +package org.intrace.output; + +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 NetworkDataSenderThread implements Runnable +{ + private final ServerSocket networkSocket; + private final BlockingQueue outgoingData = new LinkedBlockingQueue(100); + private Set set; + + public NetworkDataSenderThread(ServerSocket networkSocket) + { + this.networkSocket = networkSocket; + } + + public void start(Set set) + { + this.set = set; + + Thread networkThread = new Thread(this); + networkThread.setDaemon(true); + networkThread.setName("Network Data Sender"); + networkThread.start(); + } + + private void stop() + { + try + { + networkSocket.close(); + } + catch (IOException e) + { + // Throw away + } + set.remove(this); + System.out.println("## Network Data Connection Disconnected"); + } + + public void queueData(Object data) + { + try + { + outgoingData.put(data); + } + catch (InterruptedException e) + { + // Throw away + } + } + + @Override + public void run() + { + Socket traceSendingSocket; + try + { + traceSendingSocket = networkSocket.accept(); + try + { + ObjectOutputStream traceWriter = new ObjectOutputStream(traceSendingSocket.getOutputStream()); + while (true) + { + Object traceLine = outgoingData.take(); + traceWriter.writeObject(traceLine); + } + } + catch (Exception e) + { + traceSendingSocket.close(); + throw e; + } + } + catch (Exception e1) + { + stop(); + } + } +} diff --git a/org.intrace/src/org/intrace/output/OutputSettings.java b/org.intrace/src/org/intrace/output/OutputSettings.java new file mode 100644 index 0000000..62daa24 --- /dev/null +++ b/org.intrace/src/org/intrace/output/OutputSettings.java @@ -0,0 +1,124 @@ +package org.intrace.output; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; + +import org.intrace.shared.OutputConfigConstants; + +public class OutputSettings +{ + 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 OutputSettings(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("out-stdout-true")) + { + stdoutTraceOutputEnabled = true; + } + else if (arg.equals("out-stdout-false")) + { + stdoutTraceOutputEnabled = false; + } + else if (arg.equals("out-file-true")) + { + fileTraceOutputEnabled = true; + } + else if (arg.equals("out-file-false")) + { + fileTraceOutputEnabled = false; + } + else if (arg.startsWith("out-file1-")) + { + String file1Name = arg.replace("out-file1-", ""); + file1 = new File(file1Name); + resetTraceFiles(true, false); + } + else if (arg.startsWith("out-file2-")) + { + String file2Name = arg.replace("out-file2-", ""); + file2 = new File(file2Name); + resetTraceFiles(false, true); + } + else if (arg.equals("out-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 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(OutputConfigConstants.STD_OUT, Boolean.toString(stdoutTraceOutputEnabled)); + settingsMap.put(OutputConfigConstants.FILE_OUT, Boolean.toString(fileTraceOutputEnabled)); + return settingsMap; + } +} diff --git a/org.intrace/src/org/intrace/output/callers/CallersOutput.java b/org.intrace/src/org/intrace/output/callers/CallersOutput.java new file mode 100644 index 0000000..b9e49db --- /dev/null +++ b/org.intrace/src/org/intrace/output/callers/CallersOutput.java @@ -0,0 +1,79 @@ +package org.intrace.output.callers; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.intrace.output.AgentHelper; +import org.intrace.output.IOutputAdapter; +import org.intrace.shared.CallersConfigConstants; + +public class CallersOutput extends IOutputAdapter +{ + private final CallersSettings callersSettings = new CallersSettings(""); + private final Map recordedData = new ConcurrentHashMap(); + + @Override + public synchronized String getResponse(String args) + { + CallersSettings oldSettings = new CallersSettings(callersSettings); + callersSettings.parseArgs(args); + + if (oldSettings.isCallersEnabled() != callersSettings.isCallersEnabled()) + { + if (callersSettings.isCallersEnabled()) + { + System.out.println("## Callers Analysis Started"); + recordedData.clear(); + recordedData.put(CallersConfigConstants.MAP_ID, CallersConfigConstants.MAP_ID); + } + else + { + System.out.println("## Callers Analysis Ended"); + AgentHelper.writeDataOutput(new ConcurrentHashMap(recordedData)); + } + } + + return null; + } + + @Override + public Map getSettingsMap() + { + return callersSettings.getSettingsMap(); + } + + @Override + public void enter(String className, String methodName) + { + if (callersSettings.isCallersEnabled() + && callersSettings.getMethodRegex().matcher(methodName).matches()) + { + recordCall(); + } + } + + @SuppressWarnings("unchecked") + private synchronized void recordCall() + { + StackTraceElement[] stackTrace = new Exception().getStackTrace(); + if ((stackTrace != null) && (stackTrace.length > 3)) + { + Map treeElement = recordedData; + for (int ii = 3; ii < stackTrace.length; ii++) + { + StackTraceElement element = stackTrace[ii]; + String stackLine = element.getClassName() + "#" + + element.getMethodName() + ":" + + ((element.getLineNumber() > -1) ? element.getLineNumber() : "unknown") ; + + Object treeElementObj = treeElement.get(stackLine); + if (treeElementObj == null) + { + treeElementObj = new ConcurrentHashMap(); + treeElement.put(stackLine, treeElementObj); + } + treeElement = (Map)treeElementObj; + } + } + } +} diff --git a/org.intrace/src/org/intrace/output/callers/CallersSettings.java b/org.intrace/src/org/intrace/output/callers/CallersSettings.java new file mode 100644 index 0000000..b29d42d --- /dev/null +++ b/org.intrace/src/org/intrace/output/callers/CallersSettings.java @@ -0,0 +1,68 @@ +package org.intrace.output.callers; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +import org.intrace.shared.CallersConfigConstants; + +public class CallersSettings +{ + private boolean callersEnabled = false; + private Pattern methodsPattern = Pattern.compile(".*"); + + public CallersSettings(CallersSettings oldSettings) + { + callersEnabled = oldSettings.callersEnabled; + methodsPattern = oldSettings.methodsPattern; + } + + public CallersSettings(String args) + { + parseArgs(args); + } + + public void parseArgs(String args) + { + String[] seperateArgs = args.split("\\["); + for (int ii = 0; ii < seperateArgs.length; ii++) + { + parseArg(seperateArgs[ii]); + } + } + + private void parseArg(String arg) + { + if (arg.toLowerCase().equals("callers-enabled-false")) + { + callersEnabled = false; + } + else if (arg.toLowerCase().equals("callers-enabled-true")) + { + callersEnabled = true; + } + else if (arg.startsWith("callers-regex-")) + { + String methodsRegexStr = arg.replace("callers-regex-", ""); + methodsPattern = Pattern.compile(methodsRegexStr); + } + } + + public boolean isCallersEnabled() + { + return callersEnabled; + } + + public Pattern getMethodRegex() + { + return methodsPattern; + } + + public Map getSettingsMap() + { + Map settingsMap = new HashMap(); + settingsMap.put(CallersConfigConstants.CALLERS_ENABLED, Boolean.toString(callersEnabled)); + settingsMap.put(CallersConfigConstants.PATTERN, methodsPattern.pattern()); + return settingsMap; + } +} diff --git a/org.intrace/src/org/intrace/output/trace/TraceConfigConstants.java b/org.intrace/src/org/intrace/output/trace/TraceConfigConstants.java deleted file mode 100644 index 1891cf8..0000000 --- a/org.intrace/src/org/intrace/output/trace/TraceConfigConstants.java +++ /dev/null @@ -1,10 +0,0 @@ -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 index baa59c8..629ae25 100644 --- a/org.intrace/src/org/intrace/output/trace/TraceOutput.java +++ b/org.intrace/src/org/intrace/output/trace/TraceOutput.java @@ -1,16 +1,10 @@ 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.AgentHelper; import org.intrace.output.IOutput; /** @@ -22,16 +16,8 @@ public class TraceOutput implements IOutput 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); @@ -39,9 +25,7 @@ public class TraceOutput implements IOutput if ((oldSettings.isEntryExitTraceEnabled() != traceSettings.isEntryExitTraceEnabled()) || (oldSettings.isBranchTraceEnabled() != traceSettings.isBranchTraceEnabled()) || - (oldSettings.isArgTraceEnabled() != traceSettings.isArgTraceEnabled()) || - (oldSettings.isStdoutTraceOutputEnabled() != traceSettings.isStdoutTraceOutputEnabled()) || - (oldSettings.isFileTraceOutputEnabled() != traceSettings.isFileTraceOutputEnabled())) + (oldSettings.isArgTraceEnabled() != traceSettings.isArgTraceEnabled())) { System.out.println("## Trace Settings Changed"); } @@ -49,102 +33,21 @@ public class TraceOutput implements IOutput 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); - NetworkTraceSenderThread traceThread = new NetworkTraceSenderThread(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; - } + 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 (NetworkTraceSenderThread 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); + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + byteArg); } } @@ -152,7 +55,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + Arrays.toString(byteArrayArg)); } } @@ -162,7 +65,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + shortArg); + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + shortArg); } } @@ -170,7 +73,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + Arrays.toString(shortArrayArg)); } } @@ -180,7 +83,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + intArg); + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + intArg); } } @@ -189,7 +92,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + Arrays.toString(intArrayArg)); } } @@ -199,7 +102,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + longArg); + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + longArg); } } @@ -208,7 +111,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + Arrays.toString(longArrayArg)); } } @@ -218,7 +121,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + floatArg); + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + floatArg); } } @@ -227,7 +130,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + Arrays.toString(floatArrayArg)); } } @@ -237,7 +140,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + doubleArg); + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + doubleArg); } } @@ -246,7 +149,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + Arrays.toString(doubleArrayArg)); } } @@ -256,7 +159,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + boolArg); + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + boolArg); } } @@ -265,7 +168,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + Arrays.toString(boolArrayArg)); } } @@ -275,7 +178,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + charArg); + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + charArg); } } @@ -284,7 +187,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + Arrays.toString(charArrayArg)); } } @@ -294,7 +197,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + objArg); + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + objArg); } } @@ -302,7 +205,7 @@ public class TraceOutput implements IOutput { if (argTrace) { - writeTrace(className + ":" + methodName + ": Arg: " + AgentHelper.writeOutput(className + ":" + methodName + ": Arg: " + Arrays.toString(objArrayArg)); } } @@ -312,7 +215,7 @@ public class TraceOutput implements IOutput { if (branchTrace) { - writeTrace(className + ":" + methodName + ": /:" + lineNo); + AgentHelper.writeOutput(className + ":" + methodName + ": /:" + lineNo); } } @@ -321,7 +224,7 @@ public class TraceOutput implements IOutput { if (entryExitTrace) { - writeTrace(className + ":" + methodName + ": {"); + AgentHelper.writeOutput(className + ":" + methodName + ": {"); } } @@ -330,7 +233,7 @@ public class TraceOutput implements IOutput { if (entryExitTrace) { - writeTrace(className + ":" + methodName + ": }:" + lineNo); + AgentHelper.writeOutput(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 index c8e1ea9..03bd71f 100644 --- a/org.intrace/src/org/intrace/output/trace/TraceSettings.java +++ b/org.intrace/src/org/intrace/output/trace/TraceSettings.java @@ -1,49 +1,32 @@ 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; +import org.intrace.shared.TraceConfigConstants; + /** * Args Format: * "[arg1[arg2[arg3" - * + * * where argx is of the form * value-parameter */ public class TraceSettings { - private boolean entryExitTraceEnabled = true; + private boolean entryExitTraceEnabled = false; 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); } @@ -55,7 +38,7 @@ public class TraceSettings parseArg(seperateArgs[ii].toLowerCase()); } } - + private void parseArg(String arg) { if (arg.equals("trace-ee-false")) @@ -82,61 +65,8 @@ public class TraceSettings { 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; @@ -152,34 +82,12 @@ public class TraceSettings 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 diff --git a/org.intrace/src/org/intrace/shared/AgentConfigConstants.java b/org.intrace/src/org/intrace/shared/AgentConfigConstants.java new file mode 100644 index 0000000..59d6803 --- /dev/null +++ b/org.intrace/src/org/intrace/shared/AgentConfigConstants.java @@ -0,0 +1,11 @@ +package org.intrace.shared; + +public class AgentConfigConstants +{ + public static final String MAP_ID = "SETTINGS"; + 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/shared/CallersConfigConstants.java b/org.intrace/src/org/intrace/shared/CallersConfigConstants.java new file mode 100644 index 0000000..5537307 --- /dev/null +++ b/org.intrace/src/org/intrace/shared/CallersConfigConstants.java @@ -0,0 +1,8 @@ +package org.intrace.shared; + +public class CallersConfigConstants +{ + public static final String MAP_ID = "CALLERS"; + public static final String CALLERS_ENABLED = "CALLERS_ENABLED"; + public static final String PATTERN = "CALLERS_PATTERN"; +} diff --git a/org.intrace/src/org/intrace/shared/CallersTree.java b/org.intrace/src/org/intrace/shared/CallersTree.java new file mode 100644 index 0000000..94bc0cd --- /dev/null +++ b/org.intrace/src/org/intrace/shared/CallersTree.java @@ -0,0 +1,14 @@ +package org.intrace.shared; + +import java.util.Collection; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class CallersTree +{ + public CallersTree(String name) + { + this.name = name; + } + public final String name; + public final Collection callersChildren = new ConcurrentLinkedQueue(); +} diff --git a/org.intrace/src/org/intrace/shared/OutputConfigConstants.java b/org.intrace/src/org/intrace/shared/OutputConfigConstants.java new file mode 100644 index 0000000..cf044d4 --- /dev/null +++ b/org.intrace/src/org/intrace/shared/OutputConfigConstants.java @@ -0,0 +1,7 @@ +package org.intrace.shared; + +public class OutputConfigConstants +{ + 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/shared/TraceConfigConstants.java b/org.intrace/src/org/intrace/shared/TraceConfigConstants.java new file mode 100644 index 0000000..686f9a7 --- /dev/null +++ b/org.intrace/src/org/intrace/shared/TraceConfigConstants.java @@ -0,0 +1,8 @@ +package org.intrace.shared; + +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"; +}