package org.intrace.client.gui.helper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.miginfocom.swt.MigLayout;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.ST;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.MenuDetectEvent;
import org.eclipse.swt.events.MenuDetectListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.ProgressBar;
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.intrace.client.gui.helper.Connection.ConnectState;
import org.intrace.client.gui.helper.Connection.ISocketCallback;
import org.intrace.client.gui.helper.ControlConnectionThread.IControlConnectionListener;
import org.intrace.client.gui.helper.IncludeExcludeWindow.PatternInputCallback;
import org.intrace.client.gui.helper.NetworkDataReceiverThread.INetworkOutputConfig;
import org.intrace.client.gui.helper.TraceFilterThread.TraceFilterProgressHandler;
import org.intrace.client.gui.helper.TraceFilterThread.TraceTextHandler;
import org.intrace.shared.AgentConfigConstants;
import org.intrace.shared.TraceConfigConstants;
public class InTraceUI implements ISocketCallback, IControlConnectionListener
{
public static interface IConnectionStateCallback
{
public void setConnectionState(ConnectState state);
}
public static String NEWLINE = System.getProperty("line.separator");
private static final Pattern TRACE_LINE = Pattern.compile("^\\[[^\\]]+]:(\\[[^\\]]+\\]:([^:]+:[^:]+)):.*");
public static final Pattern ALLOW_ALL = Pattern.compile(".*");
public static final Pattern ALLOW_CLASSES = Pattern.compile("^[0-9a-zA-Z\\.\\$_]*|\\*$");
public void open()
{
placeDialogInCenter(sWindow.getDisplay().getPrimaryMonitor().getBounds(),
sWindow);
sWindow.open();
Display display = Display.getDefault();
while (!sRoot.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private final Shell sWindow;
private final Composite sRoot;
private final UIMode mode;
private final UIModeData modeData;
private IConnectionStateCallback connCallback = null;
private final MigLayout rootLayout;
// UI elements
final private MainBar mainBar;
final private ConnectionBar connBar;
final private SettingsTabs settingsTabs;
final private StartProgramBar startProgramBar;
final private OutputTabs outputTabs;
private final ConfigDataInterface configInterface;
public void setConnCallback(IConnectionStateCallback connCallback)
{
this.connCallback = connCallback;
if (connCallback != null)
{
connCallback.setConnectionState(connectionState);
}
}
public static enum UIMode
{
STANDALONE,
ECLIPSE
}
public static class UIModeData
{
public UIModeData(Color activeColorOne,
Color activeColorTwo,
Color inactiveColorOne,
Color inactiveColorTwo)
{
this.activeColorOne = activeColorOne;
this.activeColorTwo = activeColorTwo;
this.inactiveColorOne = inactiveColorOne;
this.inactiveColorTwo = inactiveColorTwo;
}
public final Color activeColorOne;
public final Color activeColorTwo;
public final Color inactiveColorOne;
public final Color inactiveColorTwo;
}
public static class ConfigDataInterface
{
public final String classIncludePattern;
public final String classExcludePattern;
public final List<String> outputIncludePattern;
public final List<String> outputExcludePattern;
public final Callback callback;
public ConfigDataInterface(String classIncludePattern,
String classExcludePattern,
List<String> outputIncludePattern,
List<String> outputExcludePattern,
Callback callback)
{
this.classIncludePattern = classIncludePattern;
this.classExcludePattern = classExcludePattern;
this.outputIncludePattern = outputIncludePattern;
this.outputExcludePattern = outputExcludePattern;
this.callback = callback;
}
public static interface Callback
{
public void setClassConfig(String classIncludePattern,
String classExcludePattern);
public void setOutputConfig(List<String> outputIncludePattern,
List<String> outputExcludePattern);
}
}
public InTraceUI(Shell xiWindow,
Composite xiRoot,
UIMode xiMode,
UIModeData xiModeData,
ConfigDataInterface xiConfigInterface)
{
sWindow = xiWindow;
sRoot = xiRoot;
mode = xiMode;
modeData = xiModeData;
configInterface = xiConfigInterface;
if ((configInterface != null) &&
(configInterface.classIncludePattern != null) &&
(configInterface.classExcludePattern != null))
{
settingsData.classRegex = configInterface.classIncludePattern;
settingsData.classExcludeRegex = configInterface.classExcludePattern;
}
rootLayout = new MigLayout("fill,hidemode 2", "[]", "0[]0[]0[]0[]0[grow]");
xiRoot.setLayout(rootLayout);
mainBar = new MainBar(xiRoot);
mainBar.composite.setLayoutData("grow,wrap,pad 0");
connBar = new ConnectionBar(xiRoot);
connBar.composite.setLayoutData("grow,wrap,pad 0");
settingsTabs = new SettingsTabs(xiRoot);
settingsTabs.composite.setLayoutData("grow,wrap,pad 0");
settingsTabs.hide();
if (mode == UIMode.STANDALONE)
{
connBar.show();
}
else
{
connBar.hide();
}
startProgramBar = new StartProgramBar(xiRoot);
startProgramBar.composite.setLayoutData("grow,wrap,pad 0");
startProgramBar.hide();
outputTabs = new OutputTabs(xiRoot);
outputTabs.composite.setLayoutData("grow,wmin 0,hmin 0");
if ((configInterface != null) &&
(configInterface.outputIncludePattern != null) &&
(configInterface.outputExcludePattern != null))
{
lastEnteredIncludeFilterPattern = configInterface.outputIncludePattern;
lastEnteredExcludeFilterPattern = configInterface.outputExcludePattern;
if (outputTabs.textOutputTab.enableFilter.getSelection())
{
outputTabs.textOutputTab.
applyPatterns(configInterface.outputIncludePattern,
configInterface.outputExcludePattern, false,
settingsTabs.localOutputSettingsTab.discardFiltered.getSelection());
}
}
updateUIStateSameThread();
sWindow.getDisplay().addFilter(SWT.KeyDown, new Listener()
{
@Override
public void handleEvent(Event e)
{
if (!sRoot.isDisposed() &&
(sWindow.getDisplay().getActiveShell() == sWindow))
{
// This is the active window
if ((outputTabs.textOutputTab != null) &&
(outputTabs.textOutputTab.textOutput != null) &&
(!outputTabs.textOutputTab.textOutput.isDisposed()) &&
outputTabs.textOutputTab.textOutput.isFocusControl())
{
// Textoutput is focused
if (((e.stateMask & SWT.CTRL) != 0) &&
(e.keyCode == 'f'))
{
outputTabs.textOutputTab.findInput.setFocus();
}
else if (((e.stateMask & SWT.CTRL) != 0) &&
(e.keyCode == SWT.ARROW_UP))
{
outputTabs.textOutputTab.findEntry();
}
else if (((e.stateMask & SWT.CTRL) != 0) &&
(e.keyCode == SWT.ARROW_DOWN))
{
outputTabs.textOutputTab.findExit();
}
}
}
else if (sRoot.isDisposed())
{
// Remove this listener
sWindow.getDisplay().removeFilter(SWT.KeyDown, this);
}
}
});
}
public void setFixedLocalConnection(final String xiPort)
{
fixedConnection = true;
if (!sRoot.isDisposed())
{
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
connBar.addressInput.setText("localhost");
connBar.portInput.setText(xiPort);
outputTabs.textOutputTab.filterThread.addSystemTraceLine("Instructions");
outputTabs.textOutputTab.filterThread.addSystemTraceLine(" - Select Classes you want to Trace");
outputTabs.textOutputTab.filterThread.addSystemTraceLine("Full help available on the Help tab");
outputTabs.textOutputTab.filterThread.addSystemTraceLine("");
setConnectionState(ConnectState.CONNECTING);
updateUIStateSameThread();
Connection.connectToAgent(thisWindow, sWindow, "localhost", xiPort);
}
});
}
}
public void setFixedLocalConnection(final Socket xiSocket)
{
fixedConnection = true;
if (!sRoot.isDisposed())
{
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
connBar.addressInput.setText("localhost");
connBar.portInput.setText("detecting...");
outputTabs.textOutputTab.filterThread.addSystemTraceLine("Instructions");
outputTabs.textOutputTab.filterThread.addSystemTraceLine(" - Select Classes you want to Trace");
outputTabs.textOutputTab.filterThread.addSystemTraceLine("Full help available on the Help tab");
outputTabs.textOutputTab.filterThread.addSystemTraceLine("");
}
});
}
setSocket(xiSocket);
}
private class MainBar
{
private final Label mainStatusLabel;
private final Button classesButton;
private final Composite composite;
private static final String UP = "\u25B2";
private static final String DOWN = "\u25BC";
private static final String RIGHT = "\u25BA";
private static final String TAHOMA_UP = "\u06F8";
private static final String TAHOMA_DOWN = "\u06F7";
private static final String TAHOMA_RIGHT = "\u003E";
private final boolean tahomaUIFont;
private final Button connectButton;
private final Button settingsButton;
private MainBar(Composite parent)
{
composite = new Composite(parent, SWT.NONE);
MigLayout barLayout;
if (mode == UIMode.STANDALONE)
{
barLayout = new MigLayout("fill", "0[100][50,center][100][15,center][grow,left][15,center][100]0", "4[]2");
}
else
{
barLayout = new MigLayout("fill", "0[100][30,center][grow,left][30,center][100]0", "4[]0");
}
composite.setLayout(barLayout);
tahomaUIFont = composite.getFont().getFontData()[0].getName().equalsIgnoreCase("tahoma");
if (mode == UIMode.STANDALONE)
{
connectButton = new Button(composite, SWT.PUSH);
if (tahomaUIFont)
{
connectButton.setText(TAHOMA_DOWN + " Connection");
}
else
{
connectButton.setText(DOWN + " Connection");
}
connectButton.setLayoutData("growx");
Label arrowLabel = new Label(composite, SWT.NONE);
if (tahomaUIFont)
{
arrowLabel.setText(TAHOMA_RIGHT);
}
else
{
arrowLabel.setText(RIGHT);
}
FontData[] defFontData = arrowLabel.getFont().getFontData();
Font newFont = new Font(Display.getCurrent(),
defFontData[0].getName(),
14,
SWT.NORMAL);
arrowLabel.setFont(newFont);
connectButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
if (connBar.composite.isVisible())
{
connBar.hide();
}
else
{
connBar.show();
}
}
});
}
else
{
connectButton = null;
}
classesButton = new Button(composite, SWT.PUSH);
classesButton.setText("Classes...");
classesButton.setLayoutData("growx");
Label barLabel1 = new Label(composite, SWT.NONE);
barLabel1.setText("|");
mainStatusLabel = new Label(composite, SWT.NONE);
mainStatusLabel.setText("Status: None");
mainStatusLabel.setLayoutData("growx");
Label barLabel2 = new Label(composite, SWT.NONE);
barLabel2.setText("|");
settingsButton = new Button(composite, SWT.PUSH);
if (tahomaUIFont)
{
settingsButton.setText(TAHOMA_DOWN + " Settings");
}
else
{
settingsButton.setText(DOWN + " Settings");
}
settingsButton.setLayoutData("growx");
settingsButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
if (settingsTabs.composite.isVisible())
{
settingsTabs.hide();
}
else
{
settingsTabs.show();
}
}
});
classesButton
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
IncludeExcludeWindow regexInput = new IncludeExcludeWindow(
ClientStrings.CLASS_TITLE, ClientStrings.CLASS_HELP_TEXT, mode,
modeData,
new PatternInputCallback()
{
private List<String> includePattern = null;
private List<String> excludePattern = null;
@Override
public void setIncludePattern(List<String> newIncludePattern)
{
includePattern = newIncludePattern;
savePatterns();
}
@Override
public void setExcludePattern(List<String> newExcludePattern)
{
excludePattern = newExcludePattern;
savePatterns();
}
private void savePatterns()
{
if ((includePattern != null) && (excludePattern != null))
{
setRegex(getStringFromList(includePattern),
getStringFromList(excludePattern));
}
}
},
getListFromString(settingsData.classRegex),
getListFromString(settingsData.classExcludeRegex),
ALLOW_ALL);
//ALLOW_CLASSES);
placeDialogInCenter(sWindow.getBounds(), regexInput.sWindow);
}
});
}
private void setStatus(int instruClasses, int totalClasses)
{
if (!sRoot.isDisposed())
{
mainStatusLabel.setText("Instrumented/Total Classes: " + instruClasses + "/"
+ totalClasses);
}
}
private void setProgress(int progressClasses, int totalClasses, boolean done)
{
if (!sRoot.isDisposed())
{
mainStatusLabel.setText("Progress: " + progressClasses + "/"
+ totalClasses);
}
}
}
private class ConnectionBar
{
final Button connectButton;
final Text addressInput;
final Text portInput;
final Composite composite;
private ConnectionBar(Composite parent)
{
MigLayout windowLayout = new MigLayout("fill", "0[40][200][100][grow]0", "4[]0");
composite = new Composite(parent, SWT.NONE);
composite.setLayout(windowLayout);
Label addressLabel = new Label(composite, SWT.NONE);
addressLabel.setText(ClientStrings.CONN_ADDRESS);
addressLabel.setLayoutData("gapx 5px,right");
addressInput = new Text(composite, SWT.BORDER);
addressInput.setText("localhost");
addressInput.setLayoutData("growx");
connectButton = new Button(composite, SWT.LEFT);
connectButton.setText(ClientStrings.CONNECT);
connectButton.setAlignment(SWT.CENTER);
connectButton.setLayoutData("gapx 5px,spany,grow,wrap");
Label portLabel = new Label(composite, SWT.NONE);
portLabel.setText(ClientStrings.CONN_PORT);
portLabel.setLayoutData("gapx 5px,right");
portInput = new Text(composite, SWT.BORDER);
portInput.setText("9123");
portInput.setLayoutData("growx");
SelectionListener connectListen = new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent selectionevent)
{
handleSelection();
}
@Override
public void widgetDefaultSelected(SelectionEvent arg0)
{
handleSelection();
}
private void handleSelection()
{
if ((connectionState == ConnectState.DISCONNECTED)
|| (connectionState == ConnectState.DISCONNECTED_ERR))
{
setConnectionState(ConnectState.CONNECTING);
updateUIStateSameThread();
Connection.connectToAgent(thisWindow, sWindow, addressInput
.getText(), portInput.getText());
} else if (connectionState == ConnectState.CONNECTED)
{
disconnect();
}
}
};
addressInput.addSelectionListener(connectListen);
portInput.addSelectionListener(connectListen);
connectButton.addSelectionListener(connectListen);
}
private void show()
{
if (mainBar.connectButton != null)
{
if (mainBar.tahomaUIFont)
{
mainBar.connectButton.setText(MainBar.TAHOMA_UP + " Connection");
}
else
{
mainBar.connectButton.setText(MainBar.UP + " Connection");
}
}
settingsTabs.hide();
composite.setVisible(true);
sRoot.layout(true, true);
}
private void hide()
{
if (mainBar.connectButton != null)
{
if (mainBar.tahomaUIFont)
{
mainBar.connectButton.setText(MainBar.TAHOMA_DOWN + " Connection");
}
else
{
mainBar.connectButton.setText(MainBar.DOWN + " Connection");
}
}
composite.setVisible(false);
sRoot.layout(true, true);
}
}
private class StartProgramBar
{
private final Composite composite;
private final Button startButton;
private StartProgramBar(Composite parent)
{
composite = new Composite(parent, SWT.NONE);
MigLayout startLayout = new MigLayout("fillx", "[align center]", "4[]0");
composite.setLayout(startLayout);
Label startLabel = new Label(composite, SWT.NONE);
startLabel.setText("Program has been paused.");
startLabel.setLayoutData("split");
startButton = new Button(composite, SWT.PUSH);
startButton.setText("Start Program");
startButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
if (controlThread != null)
{
controlThread.sendMessage(AgentConfigConstants.START_ACTIVATE);
controlThread.sendMessage("getsettings");
startButton.setEnabled(false);
}
else
{
startProgramBar.hide();
}
}
});
}
private void show()
{
startButton.setEnabled(true);
composite.setVisible(true);
sRoot.layout(true, true);
}
private void hide()
{
composite.setVisible(false);
sRoot.layout(true, true);
}
}
private class SettingsTabs
{
final private TabFolder mSettingsTabs;
final private CTabFolder mSettingsCTabs;
final private Composite composite;
final private TraceTab traceTab;
final private ExtrasTab extraTab;
final private AgentOutputSettingsTab agentOutputSettingsTab;
final private LocalOutputSettingsTab localOutputSettingsTab;
private SettingsTabs(Composite parent)
{
MigLayout windowLayout = new MigLayout("fill", "0[grow]0", "4[]0");
composite = new Composite(parent, SWT.NONE);
composite.setLayout(windowLayout);
if (mode == UIMode.STANDALONE)
{
mSettingsCTabs = null;
mSettingsTabs = new TabFolder(composite, SWT.NONE);
mSettingsTabs.setLayoutData("grow,wrap,wmin 0");
TabItem traceTabItem = new TabItem(mSettingsTabs, SWT.NONE);
traceTabItem.setText("Trace");
traceTab = new TraceTab(mSettingsTabs);
traceTabItem.setControl(traceTab.composite);
TabItem agentOutputSettingsTabItem = new TabItem(mSettingsTabs, SWT.NONE);
agentOutputSettingsTabItem.setText("Agent Output");
agentOutputSettingsTab = new AgentOutputSettingsTab(mSettingsTabs);
agentOutputSettingsTabItem.setControl(agentOutputSettingsTab.composite);
TabItem localOutputSettingsTabItem = new TabItem(mSettingsTabs, SWT.NONE);
localOutputSettingsTabItem.setText("Local Output");
localOutputSettingsTab = new LocalOutputSettingsTab(mSettingsTabs);
localOutputSettingsTabItem.setControl(localOutputSettingsTab.composite);
TabItem extraTabItem = new TabItem(mSettingsTabs, SWT.NONE);
extraTabItem.setText("Advanced");
extraTab = new ExtrasTab(mSettingsTabs);
extraTabItem.setControl(extraTab.composite);
}
else
{
mSettingsTabs = null;
mSettingsCTabs = new CTabFolder(composite, SWT.TOP | SWT.BORDER);
mSettingsCTabs.setSimple(false);
mSettingsCTabs.setLayoutData("grow,wrap,wmin 0");
if (modeData != null)
{
mSettingsCTabs.setSelectionBackground(
new Color[]{modeData.inactiveColorOne,
modeData.inactiveColorTwo},
new int[]{100}, true);
}
CTabItem traceTabItem = new CTabItem(mSettingsCTabs, SWT.NONE);
traceTabItem.setText("Trace");
traceTab = new TraceTab(mSettingsCTabs);
traceTabItem.setControl(traceTab.composite);
CTabItem agentOutputSettingsTabItem = new CTabItem(mSettingsCTabs, SWT.NONE);
agentOutputSettingsTabItem.setText("Agent Output");
agentOutputSettingsTab = new AgentOutputSettingsTab(mSettingsCTabs);
agentOutputSettingsTabItem.setControl(agentOutputSettingsTab.composite);
CTabItem localOutputSettingsTabItem = new CTabItem(mSettingsCTabs, SWT.NONE);
localOutputSettingsTabItem.setText("Local Output");
localOutputSettingsTab = new LocalOutputSettingsTab(mSettingsCTabs);
localOutputSettingsTabItem.setControl(localOutputSettingsTab.composite);
CTabItem extraTabItem = new CTabItem(mSettingsCTabs, SWT.NONE);
extraTabItem.setText("Advanced");
extraTab = new ExtrasTab(mSettingsCTabs);
extraTabItem.setControl(extraTab.composite);
mSettingsCTabs.setSelection(0);
}
}
private void show()
{
if (mainBar.tahomaUIFont)
{
mainBar.settingsButton.setText(MainBar.TAHOMA_UP + " Settings");
}
else
{
mainBar.settingsButton.setText(MainBar.UP + " Settings");
}
connBar.hide();
composite.setVisible(true);
sRoot.layout(true, true);
}
private void hide()
{
if (mainBar.tahomaUIFont)
{
mainBar.settingsButton.setText(MainBar.TAHOMA_DOWN + " Settings");
}
else
{
mainBar.settingsButton.setText(MainBar.DOWN + " Settings");
}
composite.setVisible(false);
sRoot.layout(true, true);
}
private class TraceTab
{
final Button entryExitTrace;
final Button branchTrace;
final Button argsTrace;
final Button arrayTrace;
final Button exitStackTrace;
final Composite composite;
private TraceTab(Composite parent)
{
MigLayout windowLayout = new MigLayout("fill", "[80][80][250][140][grow]");
composite = new Composite(parent, SWT.NONE);
composite.setLayout(windowLayout);
entryExitTrace = new Button(composite, SWT.CHECK);
entryExitTrace.setText(ClientStrings.ENABLE_EE_TRACE);
entryExitTrace.setAlignment(SWT.CENTER);
branchTrace = new Button(composite, SWT.CHECK);
branchTrace.setText(ClientStrings.ENABLE_BRANCH_TRACE);
branchTrace.setAlignment(SWT.CENTER);
argsTrace = new Button(composite, SWT.CHECK);
argsTrace.setText(ClientStrings.ENABLE_ARGS_TRACE);
argsTrace.setAlignment(SWT.CENTER);
arrayTrace = new Button(composite, SWT.CHECK);
arrayTrace.setText(ClientStrings.ENABLE_ARRAY_TRACE);
arrayTrace.setAlignment(SWT.CENTER);
exitStackTrace = new Button(composite, SWT.CHECK);
exitStackTrace.setText(ClientStrings.ENABLE_EXIT_STACK_TRACE);
exitStackTrace.setAlignment(SWT.CENTER);
entryExitTrace
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
toggleSetting(settingsData.entryExitEnabled, "[trace-ee-true",
"[trace-ee-false");
settingsData.entryExitEnabled = !settingsData.entryExitEnabled;
}
});
branchTrace
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
toggleSetting(settingsData.branchEnabled, "[trace-branch-true",
"[trace-branch-false");
settingsData.branchEnabled = !settingsData.branchEnabled;
}
});
argsTrace
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
toggleSetting(settingsData.argsEnabled, "[trace-args-true",
"[trace-args-false");
settingsData.argsEnabled = !settingsData.argsEnabled;
}
});
arrayTrace
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
toggleSetting(settingsData.truncArraysEnabled, TraceConfigConstants.ARRAYS + "true",
TraceConfigConstants.ARRAYS + "false");
settingsData.truncArraysEnabled = !settingsData.truncArraysEnabled;
}
});
exitStackTrace
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
toggleSetting(settingsData.exitStackTrace, "[exit-stack-trace-true",
"[exit-stack-trace-false");
settingsData.exitStackTrace = !settingsData.exitStackTrace;
}
});
}
}
private class AgentOutputSettingsTab
{
final Button stdOutOutput;
final Button fileOutput;
final Composite composite;
private AgentOutputSettingsTab(Composite parent)
{
MigLayout windowLayout = new MigLayout("fill", "[120][120][grow]");
composite = new Composite(parent, SWT.NONE);
composite.setLayout(windowLayout);
fileOutput = new Button(composite, SWT.CHECK);
fileOutput.setText(ClientStrings.ENABLE_FILE_OUTPUT);
fileOutput.setAlignment(SWT.CENTER);
stdOutOutput = new Button(composite, SWT.CHECK);
stdOutOutput.setText(ClientStrings.ENABLE_STDOUT_OUTPUT);
stdOutOutput.setAlignment(SWT.CENTER);
stdOutOutput.setVisible(false);
stdOutOutput
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
toggleSetting(settingsData.stdOutEnabled, "[out-stdout-true",
"[out-stdout-false");
settingsData.stdOutEnabled = !settingsData.stdOutEnabled;
}
});
fileOutput
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
toggleSetting(settingsData.fileOutEnabled, "[out-file-true",
"[out-file-false");
settingsData.fileOutEnabled = !settingsData.fileOutEnabled;
}
});
}
}
private class LocalOutputSettingsTab
{
final Button discardFiltered;
final Button discardExcess;
final Composite composite;
private LocalOutputSettingsTab(Composite parent)
{
MigLayout windowLayout = new MigLayout("fill", "[150][150][grow]");
composite = new Composite(parent, SWT.NONE);
composite.setLayout(windowLayout);
discardFiltered = new Button(composite, SWT.CHECK);
discardFiltered.setText(ClientStrings.DISCARD_FILTERED);
discardFiltered.setAlignment(SWT.CENTER);
discardFiltered.setSelection(true);
discardExcess = new Button(composite, SWT.CHECK);
discardExcess.setText(ClientStrings.DISCARD_EXCESS);
discardExcess.setAlignment(SWT.CENTER);
discardExcess.setSelection(true);
discardFiltered
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
outputTabs.textOutputTab.applyPatterns(activeIncludeFilterPattern, activeExcludeFilterPattern, false, discardFiltered.getSelection());
}
});
discardExcess
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
outputTabs.textOutputTab.filterThread.setDiscardExcess(
discardExcess.getSelection());
}
});
}
}
private class ExtrasTab
{
final Button togSaveClasses;
final Button togVerbose;
final Button printSettings;
final Button listClasses;
final Composite composite;
private ExtrasTab(Composite parent)
{
MigLayout windowLayout = new MigLayout("fill", "[120][120][120][160][grow]");
composite = new Composite(parent, SWT.NONE);
composite.setLayout(windowLayout);
togSaveClasses = new Button(composite, SWT.CHECK);
togSaveClasses.setText(ClientStrings.ENABLE_SAVECLASSES);
togSaveClasses.setAlignment(SWT.LEFT);
togSaveClasses.setLayoutData("growx");
togVerbose = new Button(composite, SWT.CHECK);
togVerbose.setText(ClientStrings.ENABLE_VERBOSEMODE);
togVerbose.setAlignment(SWT.LEFT);
togVerbose.setLayoutData("growx");
printSettings = new Button(composite, SWT.PUSH);
printSettings.setText(ClientStrings.DUMP_SETTINGS);
printSettings.setAlignment(SWT.CENTER);
printSettings.setLayoutData("growx");
listClasses = new Button(composite, SWT.PUSH);
listClasses.setText(ClientStrings.LIST_MODIFIED_CLASSES);
listClasses.setAlignment(SWT.CENTER);
listClasses.setLayoutData("growx");
listClasses
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
getModifiedClasses();
}
});
togSaveClasses
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
toggleSetting(settingsData.saveTracedClassfiles,
"[saveinstru-true", "[saveinstru-false");
settingsData.saveTracedClassfiles = !settingsData.saveTracedClassfiles;
}
});
togVerbose
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
toggleSetting(settingsData.verboseMode, "[verbose-true",
"[verbose-false");
settingsData.verboseMode = !settingsData.verboseMode;
}
});
printSettings
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
outputTabs.textOutputTab.filterThread.addSystemTraceLine("Settings:"
+ settingsData.toString());
}
});
}
}
}
private class OutputTabs
{
final private TabFolder mOutputTabs;
final private CTabFolder mOutputCTabs;
final private Composite composite;
final private TextOutputTab textOutputTab;
final private HelpOutputTab helpOutputTab;
private OutputTabs(Composite parent)
{
MigLayout windowLayout = new MigLayout("fill", "0[grow]0", "4[]0");
composite = new Composite(parent, SWT.NONE);
composite.setLayout(windowLayout);
if (mode == UIMode.STANDALONE)
{
mOutputCTabs = null;
mOutputTabs = new TabFolder(composite, SWT.NONE);
mOutputTabs.setLayoutData("grow,wmin 0,hmin 0");
TabItem textOutputTabItem = new TabItem(mOutputTabs, SWT.NONE);
textOutputTabItem.setText("Output");
textOutputTab = new TextOutputTab(mOutputTabs);
textOutputTabItem.setControl(textOutputTab.composite);
TabItem helpOutputTabItem = new TabItem(mOutputTabs, SWT.NONE);
helpOutputTabItem.setText("Help");
helpOutputTab = new HelpOutputTab(mOutputTabs);
helpOutputTabItem.setControl(helpOutputTab.composite);
}
else
{
mOutputTabs = null;
mOutputCTabs = new CTabFolder(composite, SWT.TOP | SWT.BORDER);
mOutputCTabs.setSimple(false);
mOutputCTabs.setLayoutData("grow,wmin 0,hmin 0");
if (modeData != null)
{
mOutputCTabs.setSelectionBackground(
new Color[]{modeData.activeColorOne,
modeData.activeColorTwo},
new int[]{100}, true);
}
CTabItem textOutputTabItem = new CTabItem(mOutputCTabs, SWT.NONE);
textOutputTabItem.setText("Output");
textOutputTab = new TextOutputTab(mOutputCTabs);
textOutputTabItem.setControl(textOutputTab.composite);
CTabItem helpOutputTabItem = new CTabItem(mOutputCTabs, SWT.NONE);
helpOutputTabItem.setText("Help");
helpOutputTab = new HelpOutputTab(mOutputCTabs);
helpOutputTabItem.setControl(helpOutputTab.composite);
mOutputCTabs.setSelection(0);
}
}
private class TextOutputTab
{
final StyledText textOutput;
final TraceFilterThread filterThread;
final Button textFilter;
final ProgressBar pBar;
final Button cancelButton;
final Button networkOutput;
final Button enableFilter;
final Label statusLabel;
final Button downButton;
final Button upButton;
final Text findInput;
final Composite composite;
final Color findDefaultBack;
final Color findDefaultFore;
final Font downButtonDefFont;
final Font downButtonBoldFont;
final Font upButtonDefFont;
final Font upButtonBoldFont;
private TextOutputTab(Composite parent)
{
MigLayout windowLayout = new MigLayout("fill,wmin 0,hmin 0",
"[90][90][15,center][90][grow][90][align right,100]", "[][][grow][]");
composite = new Composite(parent, SWT.NONE);
composite.setLayout(windowLayout);
Button saveText = new Button(composite, SWT.PUSH);
saveText.setText(ClientStrings.SAVE_TEXT);
saveText.setLayoutData("grow");
Button clearText = new Button(composite, SWT.PUSH);
clearText.setText(ClientStrings.CLEAR_TEXT);
clearText.setLayoutData("grow");
Label barLabel1 = new Label(composite, SWT.NONE);
barLabel1.setText("|");
textFilter = new Button(composite, SWT.PUSH);
textFilter.setText(ClientStrings.FILTER_TEXT);
textFilter.setLayoutData("grow");
Button resetMethodFilterBtn = new Button(composite, SWT.PUSH);
resetMethodFilterBtn.setText(ClientStrings.RESET_METHOD_FILTER);
pBar = new ProgressBar(composite, SWT.NORMAL);
pBar.setLayoutData("grow");
pBar.setVisible(false);
cancelButton = new Button(composite, SWT.PUSH);
cancelButton.setText(ClientStrings.CANCEL_TEXT);
cancelButton.setLayoutData("grow");
cancelButton.setVisible(false);
Button autoScrollBtn = new Button(composite, SWT.CHECK);
autoScrollBtn.setText(ClientStrings.AUTO_SCROLL);
autoScrollBtn.setLayoutData("wrap");
autoScrollBtn.setSelection(autoScroll);
networkOutput = new Button(composite, SWT.CHECK);
networkOutput.setText(ClientStrings.ENABLE_NETWORK_OUTPUT);
networkOutput.setLayoutData("grow");
networkOutput.setSelection(true);
enableFilter = new Button(composite, SWT.CHECK);
enableFilter.setText(ClientStrings.ENABLE_FILTER);
enableFilter.setLayoutData("skip 2");
enableFilter.setSelection(true);
Button enableMethodFilter = new Button(composite, SWT.CHECK);
enableMethodFilter.setText(ClientStrings.ENABLE_METHOD_FILTER);
enableMethodFilter.setLayoutData("wrap");
enableMethodFilter.setSelection(false);
textOutput = new StyledText(composite, SWT.MULTI | SWT.V_SCROLL
| SWT.H_SCROLL | SWT.BORDER);
textOutput.setEditable(false);
textOutput.setLayoutData("spanx,grow,wmin 0,hmin 0,wrap");
textOutput.setBackground(Display.getCurrent().getSystemColor(
SWT.COLOR_WHITE));
textOutput.setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP);
textOutput.setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN);
textOutput.addMenuDetectListener(new MenuDetectListener()
{
@Override
public void menuDetected(MenuDetectEvent e)
{
if (e.widget == textOutput)
{
Menu textMenu = new Menu(sWindow, SWT.POP_UP);
// Extract current line of text
String line = getCurrentLine();
// Check if it is a trace line
Matcher traceLineMatcher = TRACE_LINE.matcher(line);
if (traceLineMatcher.matches())
{
final String matchStr = traceLineMatcher.group(1);
final String methodStr = traceLineMatcher.group(2);
MenuItem entryItem = new MenuItem(textMenu, SWT.PUSH);
entryItem.setText("Find method entry: " + methodStr + ": {");
entryItem.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
findInput.setText(matchStr + ": {");
doFind(false);
}
});
MenuItem excludeItem = new MenuItem(textMenu, SWT.PUSH);
excludeItem.setText("Find method exit: " + methodStr + ": }");
excludeItem.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
findInput.setText(matchStr + ": }");
doFind(true);
}
});
}
final String selectedText = textOutput.getSelectionText();
if ((selectedText.length() > 0) && !selectedText.contains("\n"))
{
MenuItem includeItem = new MenuItem(textMenu, SWT.PUSH);
includeItem.setText("Include: " + selectedText);
includeItem.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
List<String> newIncludePattern = new ArrayList<String>(lastEnteredIncludeFilterPattern);
if (lastEnteredIncludeFilterPattern.equals(TraceFilterThread.MATCH_ALL))
{
newIncludePattern.clear();
}
String newPattern = selectedText;
if (!newIncludePattern.contains(newPattern))
{
newIncludePattern.add(newPattern);
lastEnteredIncludeFilterPattern = newIncludePattern;
if (enableFilter.getSelection())
{
applyPatterns(lastEnteredIncludeFilterPattern,
lastEnteredExcludeFilterPattern, false,
settingsTabs.localOutputSettingsTab.discardFiltered.getSelection());
}
}
}
});
MenuItem excludeItem = new MenuItem(textMenu, SWT.PUSH);
excludeItem.setText("Exclude: " + selectedText);
excludeItem.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
List<String> newExcludePattern = new ArrayList<String>(lastEnteredExcludeFilterPattern);
String newPattern = selectedText;
if (!newExcludePattern.contains(newPattern))
{
newExcludePattern.add(newPattern);
lastEnteredExcludeFilterPattern = newExcludePattern;
if (enableFilter.getSelection())
{
applyPatterns(lastEnteredIncludeFilterPattern,
lastEnteredExcludeFilterPattern, false,
settingsTabs.localOutputSettingsTab.discardFiltered.getSelection());
}
}
}
});
}
if (textMenu.getItemCount() > 0)
{
textOutput.setMenu(textMenu);
}
else
{
textOutput.setMenu(null);
}
}
}
});
MigLayout barLayout = new MigLayout("fill,wmin 0,hmin 0",
"0[][grow][][200][][]0", "0[]0");
final Composite compositeBar = new Composite(composite, SWT.NONE);
compositeBar.setLayout(barLayout);
compositeBar.setLayoutData("spanx,growx,pad 0");
statusLabel = new Label(compositeBar, SWT.NONE);
setOutputStatus(0, 0);
statusLabel.setLayoutData("growx,skip");
Label findLabel = new Label(compositeBar, SWT.NONE);
findLabel.setText("Find:");
findInput = new Text(compositeBar, SWT.BORDER);
findInput.setLayoutData("growx");
findDefaultBack = findInput.getBackground();
findDefaultFore = findInput.getForeground();
downButton = new Button(compositeBar, SWT.PUSH);
downButton.setText("Down");
downButton.setAlignment(SWT.CENTER);
downButtonDefFont = downButton.getFont();
FontData[] downDefData = downButtonDefFont.getFontData();
downButtonBoldFont = new Font(Display.getCurrent(),
downDefData[0].getName(),
downDefData[0].getHeight(),
SWT.BOLD);
upButton = new Button(compositeBar, SWT.PUSH);
upButton.setText("Up");
upButton.setAlignment(SWT.CENTER);
upButtonDefFont = downButton.getFont();
FontData[] upDefData = upButtonDefFont.getFontData();
upButtonBoldFont = new Font(Display.getCurrent(),
upDefData[0].getName(),
upDefData[0].getHeight(),
SWT.BOLD);
SelectionListener findListen = new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent selectionevent)
{
doFind(true);
}
@Override
public void widgetDefaultSelected(SelectionEvent arg0)
{
doFind(true);
}
};
downButton.addSelectionListener(findListen);
findInput.addSelectionListener(findListen);
findInput.addModifyListener(new ModifyListener()
{
@Override
public void modifyText(ModifyEvent arg0)
{
if (!composite.isDisposed())
{
findInput.setForeground(findDefaultFore);
findInput.setBackground(findDefaultBack);
downButton.setFont(downButtonDefFont);
upButton.setFont(upButtonDefFont);
}
}
});
upButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
doFind(false);
}
});
clearText
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
MessageBox messageBox = new MessageBox(sWindow, SWT.ICON_WARNING |SWT.YES | SWT.NO);
messageBox.setMessage("Clear all output?");
messageBox.setText("Output");
int rc = messageBox.open();
if (rc == SWT.YES)
{
filterThread.setClearTrace();
}
}
});
autoScrollBtn
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
autoScroll = !autoScroll;
}
});
enableMethodFilter
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
filterThread.methodFilterRecordingEnabled = !filterThread.methodFilterRecordingEnabled;
}
});
resetMethodFilterBtn
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
filterThread.resetMethodFilter();
}
});
networkOutput
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
toggleSetting(settingsData.netOutEnabled, "[out-network-true",
"[out-network-false");
settingsData.netOutEnabled = !settingsData.netOutEnabled;
}
});
saveText.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
FileDialog dialog = new FileDialog(sWindow, SWT.SAVE);
dialog.setFilterNames(new String[] { "Text Files", "All Files (*.*)" });
dialog.setFilterExtensions(new String[] { "*.txt", "*.*" });
dialog.setFileName("output.txt");
String fileName = dialog.open();
if (fileName != null)
{
try
{
Writer out = new OutputStreamWriter(new FileOutputStream(new File(fileName)));
out.append(textOutput.getText());
out.flush();
out.close();
MessageBox messageBox = new MessageBox(sWindow, SWT.ICON_INFORMATION | SWT.OK);
messageBox.setText("Save Complete");
messageBox.setMessage("Output Saved");
messageBox.open();
}
catch (IOException e)
{
MessageBox messageBox = new MessageBox(sWindow, SWT.ICON_INFORMATION | SWT.OK);
messageBox.setText("Save Error");
messageBox.setMessage("Error: " + e.toString());
messageBox.open();
}
}
}
});
final PatternInputCallback patternCallback = new PatternInputCallback()
{
private List<String> includePattern = null;
private List<String> excludePattern = null;
@Override
public void setIncludePattern(List<String> newIncludePattern)
{
includePattern = newIncludePattern;
savePatterns();
}
@Override
public void setExcludePattern(List<String> newExcludePattern)
{
excludePattern = newExcludePattern;
savePatterns();
}
private void savePatterns()
{
if ((includePattern != null) && (excludePattern != null))
{
if (includePattern.equals(TraceFilterThread.MATCH_NONE) &&
excludePattern.equals(TraceFilterThread.MATCH_NONE))
{
includePattern = TraceFilterThread.MATCH_ALL;
}
lastEnteredIncludeFilterPattern = includePattern;
lastEnteredExcludeFilterPattern = excludePattern;
if (configInterface != null)
{
configInterface.callback.setOutputConfig(includePattern, excludePattern);
}
if (enableFilter.getSelection())
{
applyPatterns(includePattern, excludePattern, false,
settingsTabs.localOutputSettingsTab.discardFiltered.getSelection());
}
}
}
};
textFilter
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
IncludeExcludeWindow regexInput;
regexInput = new IncludeExcludeWindow("Output Filter", ClientStrings.FILTER_HELP_TEXT, mode,
modeData,
patternCallback, lastEnteredIncludeFilterPattern,
lastEnteredExcludeFilterPattern, ALLOW_ALL);
placeDialogInCenter(sWindow.getBounds(), regexInput.sWindow);
}
});
enableFilter
.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
if (enableFilter.getSelection())
{
applyPatterns(lastEnteredIncludeFilterPattern,
lastEnteredExcludeFilterPattern, true,
settingsTabs.localOutputSettingsTab.discardFiltered.getSelection());
}
else
{
applyPatterns(TraceFilterThread.MATCH_ALL,
TraceFilterThread.MATCH_NONE, true,
settingsTabs.localOutputSettingsTab.discardFiltered.getSelection());
}
}
});
filterThread = new TraceFilterThread(new TraceTextHandler()
{
// Re-usable class to avoid object allocations
class SetTextRunnable implements Runnable
{
String traceText = null;
@Override
public void run()
{
if (!sRoot.isDisposed())
{
textOutput.setRedraw(false);
textOutput.setText(traceText);
if (autoScroll)
{
textOutput.setTopIndex(Integer.MAX_VALUE);
}
textOutput.setRedraw(true);
}
}
}
SetTextRunnable mSetTextRunnable = new SetTextRunnable();
@Override
public void setText(String traceText)
{
if (sRoot.isDisposed())
return;
mSetTextRunnable.traceText = traceText;
sWindow.getDisplay().syncExec(mSetTextRunnable);
mSetTextRunnable.traceText = null;
}
// Re-usable class to avoid object allocations
class AppendTextRunnable implements Runnable
{
String traceText = null;
@Override
public void run()
{
if (!sRoot.isDisposed())
{
textOutput.append(traceText);
if (autoScroll)
{
textOutput.setTopIndex(Integer.MAX_VALUE);
}
}
}
}
AppendTextRunnable mAppendTextRunnable = new AppendTextRunnable();
@Override
public void appendText(final String traceText)
{
if (sRoot.isDisposed())
return;
mAppendTextRunnable.traceText = traceText;
sWindow.getDisplay().syncExec(mAppendTextRunnable);
mAppendTextRunnable.traceText = null;
}
@Override
public void setStatus(int displayed, int total)
{
setOutputStatus(displayed, total);
}
});
if (mode == UIMode.STANDALONE)
{
filterThread.addSystemTraceLine("Instructions");
filterThread.addSystemTraceLine("(1) Connect to Agent");
filterThread.addSystemTraceLine("(2) Select Classes you want to Trace");
filterThread.addSystemTraceLine("Full help available on the Help tab");
filterThread.addSystemTraceLine("");
}
}
public void findEntry()
{
// Extract current line of text
String line = getCurrentLine();
// Check if it is a trace line
Matcher traceLineMatcher = TRACE_LINE.matcher(line);
if (traceLineMatcher.matches())
{
String matchStr = traceLineMatcher.group(1);
findInput.setText(matchStr + ": {");
doFind(false);
}
}
public void findExit()
{
// Extract current line of text
String line = getCurrentLine();
// Check if it is a trace line
Matcher traceLineMatcher = TRACE_LINE.matcher(line);
if (traceLineMatcher.matches())
{
String matchStr = traceLineMatcher.group(1);
findInput.setText(matchStr + ": }");
doFind(true);
}
}
private String getCurrentLine()
{
Point linePoint = textOutput.getSelection();
int lineOffset = linePoint.x;
String line = "";
if (lineOffset != -1)
{
String text = textOutput.getText();
String earlierText = text.substring(0, lineOffset);
int startIndex = earlierText.lastIndexOf("\n");
int endIndex = text.indexOf("\n", lineOffset);
if ((startIndex != -1) && (endIndex != -1))
{
line = text.substring(startIndex + 1, endIndex - 1);
}
}
return line;
}
private void doFind(final boolean down)
{
if (!sRoot.isDisposed())
{
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
String searchText = findInput.getText();
if ((searchText != null) &&
(searchText.length() > 0) &&
(textOutput.getCharCount() > 0))
{
if (down)
{
downButton.setFont(downButtonBoldFont);
upButton.setFont(downButtonDefFont);
}
else
{
downButton.setFont(downButtonDefFont);
upButton.setFont(upButtonBoldFont);
}
String fullText = textOutput.getText();
int startIndex = textOutput.getCaretOffset();
int nextIndex;
if (down)
{
nextIndex = fullText.indexOf(searchText, startIndex);
}
else
{
nextIndex = fullText.lastIndexOf(searchText, startIndex - searchText.length());
Point selection = textOutput.getSelection();
if ((nextIndex == selection.x) || (nextIndex == selection.y))
{
nextIndex = fullText.lastIndexOf(searchText, startIndex - searchText.length() - 1);
}
}
if (nextIndex > -1)
{
textOutput.setSelectionRange(nextIndex, searchText.length());
int lineIndex = textOutput.getLineAtOffset(nextIndex);
textOutput.setTopIndex(lineIndex);
findInput.setForeground(findDefaultFore);
findInput.setBackground(findDefaultBack);
}
else
{
Display disp = sWindow.getDisplay();
findInput.setBackground(new Color(Display.getCurrent(), 255, 200, 200));
findInput.setForeground(disp.getSystemColor(SWT.COLOR_BLACK));
}
}
}
});
}
}
// Re-usable class to avoid object allocations
class SetOutputStatusRunnable implements Runnable
{
int displayed;
int total;
@Override
public void run()
{
if (!sRoot.isDisposed())
{
if (activeDiscardFiltered)
{
statusLabel.setText("Displayed lines: " + displayed);
}
else
{
statusLabel.setText("Displayed lines: " + displayed + ", Total lines: " + total);
}
}
}
}
SetOutputStatusRunnable mSetOutputStatusRunnable = new SetOutputStatusRunnable();
public void setOutputStatus(final int displayed, final int total)
{
if (!sRoot.isDisposed())
{
mSetOutputStatusRunnable.displayed = displayed;
mSetOutputStatusRunnable.total = total;
sWindow.getDisplay().syncExec(mSetOutputStatusRunnable);
}
}
private void applyPatterns(List<String> newIncludePattern,
List<String> newExcludePattern,
final boolean isToggle,
final boolean isDiscardFiltered)
{
if (newIncludePattern.equals(activeIncludeFilterPattern)
&& newExcludePattern.equals(activeExcludeFilterPattern) &&
isDiscardFiltered == activeDiscardFiltered)
{
return;
}
else
{
oldIncludeFilterPattern = activeIncludeFilterPattern;
oldExcludeFilterPattern = activeExcludeFilterPattern;
activeIncludeFilterPattern = newIncludePattern;
activeExcludeFilterPattern = newExcludePattern;
activeDiscardFiltered = isDiscardFiltered;
}
if (sRoot.isDisposed())
return;
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
enableFilter.setEnabled(false);
textFilter.setEnabled(false);
pBar.setVisible(true);
cancelButton.setVisible(true);
final boolean[] filterCancelled = new boolean[]
{ false };
final SelectionListener cancelListener = new org.eclipse.swt.events.SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
filterCancelled[0] = true;
}
};
cancelButton.addSelectionListener(cancelListener);
final List<String> newIncludePattern = activeIncludeFilterPattern;
final List<String> newExcludePattern = activeExcludeFilterPattern;
final TraceFilterProgressHandler progressHandler = new TraceFilterProgressHandler()
{
@Override
public boolean setProgress(final int percent)
{
if (sRoot.isDisposed())
return false;
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
if (percent < 100)
{
pBar.setSelection(percent);
} else
{
pBar.setVisible(false);
cancelButton.setVisible(false);
cancelButton.removeSelectionListener(cancelListener);
textFilter.setEnabled(true);
enableFilter.setEnabled(true);
if (filterCancelled[0])
{
activeIncludeFilterPattern = oldIncludeFilterPattern;
activeExcludeFilterPattern = oldExcludeFilterPattern;
if (isToggle)
{
enableFilter.setSelection(!enableFilter.getSelection());
}
}
}
}
});
return filterCancelled[0];
}
@Override
public List<String> getIncludePattern()
{
return newIncludePattern;
}
@Override
public List<String> getExcludePattern()
{
return newExcludePattern;
}
@Override
public boolean discardFiltered()
{
return isDiscardFiltered;
}
};
filterThread.applyFilter(progressHandler);
}
});
}
}
private class HelpOutputTab
{
final StyledText textOutput;
final Composite composite;
final Link helpLink;
private HelpOutputTab(Composite parent)
{
MigLayout windowLayout = new MigLayout("fill,wmin 0,hmin 0",
"[grow]", "[][grow]");
composite = new Composite(parent, SWT.NONE);
composite.setLayout(windowLayout);
helpLink = new Link(composite, SWT.NONE);
helpLink.setLayoutData("growx,wrap");
helpLink.setText("<A HREF=\"http://mchr3k.github.com/org.intrace/\">Online Help</A>");
textOutput = new StyledText(composite, SWT.MULTI | SWT.V_SCROLL
| SWT.H_SCROLL | SWT.BORDER);
textOutput.setEditable(false);
textOutput.setLayoutData("spanx,grow,wmin 0,hmin 0");
textOutput.setBackground(Display.getCurrent().getSystemColor(
SWT.COLOR_WHITE));
helpLink.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent event)
{
Program.launch(event.text);
}
});
StringBuilder helpStr = new StringBuilder();
helpStr.append("Here is some example trace:\n");
helpStr.append("[14:14:30]:[1]:example.ExampleClass:multiplyMethod: {:100\n");
helpStr.append("[14:14:30]:[1]:example.ExampleClass:multiplyMethod: Arg: 2\n");
helpStr.append("[14:14:30]:[1]:example.ExampleClass:multiplyMethod: Arg: 4\n");
helpStr.append("[14:14:30]:[1]:example.ExampleClass:multiplyMethod: /:101\n");
helpStr.append("[14:14:30]:[1]:example.ExampleClass:multiplyMethod: Return: 8\n");
helpStr.append("[14:14:30]:[1]:example.ExampleClass:multiplyMethod: }:105\n");
helpStr.append("\n");
helpStr.append("This means the following:\n");
helpStr.append("[14:14:30] is a timestamp");
helpStr.append("[1] - the thread ID\n");
helpStr.append("example.ExampleClass:multiplyMethod - the Class and Method being traced\n");
helpStr.append("{:100 - The method was entered on source line 100\n");
helpStr.append("Arg: 2 - The first argument had value 2\n");
helpStr.append("Arg: 2 - The second argument had value 4\n");
helpStr.append("/:101 - An optional block of code was executed starting at source line 101 (e.g. an if statement)\n");
helpStr.append("Return: 8 - The method returned value 8\n");
helpStr.append("}:105 - The method returned on source line 105\n");
textOutput.setText(helpStr.toString());
}
}
}
// Window ref
private final InTraceUI thisWindow = this;
private ConnectState connectionState = ConnectState.DISCONNECTED;
public void setConnectionState(ConnectState connectionState)
{
this.connectionState = connectionState;
if (connectionState == ConnectState.CONNECTED)
{
if (!sWindow.isDisposed())
{
sWindow.getDisplay().syncExec(new Runnable()
{
@Override
public void run()
{
connBar.hide();
}
});
}
}
IConnectionStateCallback callback = connCallback;
if (callback != null)
{
callback.setConnectionState(connectionState);
}
}
// Network details
private InetAddress remoteAddress;
// Threads
private NetworkDataReceiverThread networkTraceThread;
private ControlConnectionThread controlThread;
// Settings
private ParsedSettingsData settingsData = new ParsedSettingsData(new HashMap<String, String>());
private List<String> lastEnteredIncludeFilterPattern = TraceFilterThread.MATCH_ALL;
private List<String> activeIncludeFilterPattern = TraceFilterThread.MATCH_ALL;
private List<String> oldIncludeFilterPattern = TraceFilterThread.MATCH_ALL;
private List<String> lastEnteredExcludeFilterPattern = TraceFilterThread.MATCH_NONE;
private List<String> activeExcludeFilterPattern = TraceFilterThread.MATCH_NONE;
private List<String> oldExcludeFilterPattern = TraceFilterThread.MATCH_NONE;
private boolean activeDiscardFiltered = true;
private boolean autoScroll = true;
private boolean fixedConnection = false;
@Override
public void setSocket(Socket socket)
{
if (socket != null)
{
setConnectionStatus("Connected");
remoteAddress = socket.getInetAddress();
controlThread = new ControlConnectionThread(socket, this);
controlThread.start();
if ((configInterface != null) &&
(configInterface.classIncludePattern != null) &&
(configInterface.classExcludePattern != null))
{
controlThread.sendMessage(
AgentConfigConstants.CLASS_REGEX + configInterface.classIncludePattern
+ AgentConfigConstants.EXCLUDE_CLASS_REGEX + configInterface.classExcludePattern);
}
controlThread.sendMessage("getsettings");
setConnectionState(ConnectState.CONNECTED);
controlThread.sendMessage("[out-network");
String networkTracePortStr = controlThread.getMessage();
int networkTracePort = Integer.parseInt(networkTracePortStr);
try
{
INetworkOutputConfig config = new INetworkOutputConfig()
{
@Override
public boolean isNetOutputEnabled()
{
return settingsData.netOutEnabled;
}
};
networkTraceThread = new NetworkDataReceiverThread(remoteAddress,
networkTracePort, config, outputTabs.textOutputTab.filterThread);
networkTraceThread.start();
} catch (IOException ex)
{
outputTabs.textOutputTab.filterThread
.addSystemTraceLine(
"Failed to setup network trace: " + ex.toString() + "\n" +
"Remote address: " + remoteAddress + "\n" +
"Remote port: " + networkTracePortStr);
}
} else
{
setConnectionState(ConnectState.DISCONNECTED_ERR);
}
updateUIState();
}
@Override
public void disconnect()
{
if (controlThread != null)
{
controlThread.disconnect();
}
if (networkTraceThread != null)
{
networkTraceThread.disconnect();
}
setConnectionState(ConnectState.DISCONNECTED);
updateUIState();
}
private void getModifiedClasses()
{
new Thread(new Runnable()
{
@Override
public void run()
{
controlThread.sendMessage("[listmodifiedclasses");
String modifiedClasses = controlThread.getMessage();
if (modifiedClasses.length() <= 2)
{
outputTabs.textOutputTab.filterThread.addSystemTraceLine("No instrumented classes");
}
else
{
modifiedClasses = modifiedClasses.substring(1, modifiedClasses
.length() - 1);
String[] classNames = modifiedClasses.split(",");
for (String className : classNames)
{
outputTabs.textOutputTab.filterThread.addSystemTraceLine("Instrumented: "
+ (className != null ? className.trim() : "null"));
}
}
}
}).start();
}
public void setRegex(final String includePattern, final String excludePattern)
{
if (!sRoot.isDisposed())
{
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
String tmpInclude = includePattern.replace('[', '{');
String tmpExclude = excludePattern.replace('[', '{');
settingsData.classRegex = tmpInclude;
settingsData.classExcludeRegex = tmpExclude;
controlThread.sendMessage(AgentConfigConstants.CLASS_REGEX + tmpInclude
+ AgentConfigConstants.EXCLUDE_CLASS_REGEX + tmpExclude);
controlThread.sendMessage("getsettings");
}
});
}
}
public void setCallersRegex(final String regex)
{
controlThread.sendMessage("[callers-start-" + regex);
}
private void toggleSetting(final boolean settingValue,
final String enableCommand, final String disableCommand)
{
if (!sRoot.isDisposed())
{
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
if (settingValue)
{
controlThread.sendMessage(disableCommand);
} else
{
controlThread.sendMessage(enableCommand);
}
controlThread.sendMessage("getsettings");
}
});
}
}
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 updateUIState()
{
if (!sRoot.isDisposed())
{
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
updateUIStateSameThread();
}
});
}
}
private void updateUIStateSameThread()
{
if (fixedConnection)
{
connBar.portInput.setText(Integer.toString(settingsData.actualServerPort));
}
if (settingsData.waitStart)
{
startProgramBar.show();
}
else
{
startProgramBar.hide();
}
if (connectionState == ConnectState.CONNECTING)
{
connBar.connectButton.setText(ClientStrings.CONNECTING);
connBar.connectButton.setEnabled(false);
connBar.addressInput.setEnabled(false);
connBar.portInput.setEnabled(false);
}
else
{
chooseText(connBar.connectButton,
(connectionState == ConnectState.CONNECTED), ClientStrings.CONNECT,
ClientStrings.DISCONNECT);
if (connectionState == ConnectState.CONNECTED)
{
// Disable connection details
connBar.addressInput.setEnabled(false);
connBar.portInput.setEnabled(false);
// Enable all buttons
mainBar.classesButton.setEnabled(true);
settingsTabs.extraTab.listClasses.setEnabled(true);
settingsTabs.traceTab.argsTrace.setEnabled(true);
settingsTabs.traceTab.branchTrace.setEnabled(true);
settingsTabs.traceTab.exitStackTrace.setEnabled(true);
settingsTabs.traceTab.entryExitTrace.setEnabled(true);
settingsTabs.traceTab.arrayTrace.setEnabled(true);
settingsTabs.agentOutputSettingsTab.fileOutput.setEnabled(true);
settingsTabs.agentOutputSettingsTab.stdOutOutput.setEnabled(true);
settingsTabs.extraTab.togSaveClasses.setEnabled(true);
settingsTabs.extraTab.togVerbose.setEnabled(true);
settingsTabs.extraTab.printSettings.setEnabled(true);
outputTabs.textOutputTab.networkOutput.setEnabled(true);
// Update the button pressed/unpressed state
settingsTabs.traceTab.argsTrace.setSelection(settingsData.argsEnabled);
settingsTabs.traceTab.branchTrace.setSelection(settingsData.branchEnabled);
settingsTabs.traceTab.exitStackTrace.setSelection(settingsData.exitStackTrace);
settingsTabs.traceTab.entryExitTrace.setSelection(settingsData.entryExitEnabled);
settingsTabs.traceTab.arrayTrace.setSelection(settingsData.truncArraysEnabled);
settingsTabs.agentOutputSettingsTab.fileOutput.setSelection(settingsData.fileOutEnabled);
settingsTabs.agentOutputSettingsTab.stdOutOutput.setSelection(settingsData.stdOutEnabled);
settingsTabs.extraTab.togSaveClasses.setSelection(settingsData.saveTracedClassfiles);
settingsTabs.extraTab.togVerbose.setSelection(settingsData.verboseMode);
outputTabs.textOutputTab.networkOutput.setSelection(settingsData.netOutEnabled);
// Update number of classes
mainBar.setStatus(settingsData.instruClasses,
settingsData.totalClasses);
}
// Only reset status text if we didn't hit an error
if (connectionState == ConnectState.DISCONNECTED)
{
setConnectionStatus("Disconnected");
}
// Always reset button states
if ((connectionState == ConnectState.DISCONNECTED)
|| (connectionState == ConnectState.DISCONNECTED_ERR))
{
if (!fixedConnection)
{
connBar.addressInput.setEnabled(true);
connBar.portInput.setEnabled(true);
}
startProgramBar.hide();
mainBar.classesButton.setEnabled(false);
settingsTabs.extraTab.listClasses.setEnabled(false);
settingsTabs.traceTab.argsTrace.setEnabled(false);
settingsTabs.traceTab.branchTrace.setEnabled(false);
settingsTabs.traceTab.exitStackTrace.setEnabled(false);
settingsTabs.traceTab.entryExitTrace.setEnabled(false);
settingsTabs.traceTab.arrayTrace.setEnabled(false);
settingsTabs.agentOutputSettingsTab.fileOutput.setEnabled(false);
settingsTabs.agentOutputSettingsTab.stdOutOutput.setEnabled(false);
settingsTabs.extraTab.togSaveClasses.setEnabled(false);
settingsTabs.extraTab.togVerbose.setEnabled(false);
settingsTabs.extraTab.printSettings.setEnabled(false);
outputTabs.textOutputTab.networkOutput.setEnabled(false);
}
}
}
@Override
public void setConnectionStatus(final String statusText)
{
if (!sRoot.isDisposed())
{
sWindow.getDisplay().syncExec(new Runnable()
{
@Override
public void run()
{
mainBar.mainStatusLabel.setText(statusText);
}
});
}
}
@Override
public void setProgress(final Map<String, String> progressMap)
{
if (!sRoot.isDisposed())
{
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
int numDone = Integer.parseInt(progressMap
.get(AgentConfigConstants.NUM_PROGRESS_COUNT));
int numTotal = Integer.parseInt(progressMap
.get(AgentConfigConstants.NUM_PROGRESS_TOTAL));
boolean done = (progressMap
.get(AgentConfigConstants.NUM_PROGRESS_DONE) != null);
mainBar.setProgress(numDone, numTotal, done);
}
});
}
}
@Override
public void setStatus(final Map<String, String> statusMap)
{
if (!sRoot.isDisposed())
{
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
int numInstr = Integer.parseInt(statusMap
.get(AgentConfigConstants.STINST));
int numTotal = Integer.parseInt(statusMap
.get(AgentConfigConstants.STCLS));
mainBar.setStatus(numInstr, numTotal);
}
});
}
}
@Override
public void setConfig(final Map<String, String> settingsMap)
{
if (!sRoot.isDisposed())
{
sWindow.getDisplay().asyncExec(new Runnable()
{
@Override
public void run()
{
outputTabs.textOutputTab.filterThread
.addSystemTraceLine("Latest Settings Received");
settingsData = new ParsedSettingsData(settingsMap);
if ((configInterface != null) &&
(settingsData.classRegex != null) &&
(settingsData.classExcludeRegex != null))
{
configInterface.callback.setClassConfig(settingsData.classRegex,
settingsData.classExcludeRegex);
}
setConnectionState(ConnectState.CONNECTED);
updateUIStateSameThread();
}
});
}
}
public static void placeDialogInCenter(Rectangle parentSize, Shell shell)
{
Rectangle mySize = shell.getBounds();
int locationX, locationY;
locationX = (parentSize.width - mySize.width) / 2 + parentSize.x;
locationY = (parentSize.height - mySize.height) / 2 + parentSize.y;
shell.setLocation(new Point(locationX, locationY));
shell.open();
}
public void dispose()
{
disconnect();
outputTabs.textOutputTab.filterThread.interrupt();
}
public static List<String> getListFromString(String pattern)
{
List<String> items = new ArrayList<String>();
String[] patternParts = pattern.split("\\|");
for (String part : patternParts)
{
items.add(part);
}
return items;
}
public static String getStringFromList(List<String> list)
{
StringBuilder str = new StringBuilder();
for (int ii = 0; ii < list.size(); ii++)
{
String item = list.get(ii);
str.append(item);
if (ii < (list.size() - 1))
{
str.append("|");
}
}
return str.toString();
}
public static Image[] getIcons(Display display) throws IOException
{
// Load icons
ClassLoader loader = InTraceUI.class.getClassLoader();
InputStream is16 = loader.getResourceAsStream(
"org/intrace/icons/intrace16.gif");
Image icon16 = new Image(display, is16);
is16.close();
InputStream is32 = loader.getResourceAsStream(
"org/intrace/icons/intrace32.gif");
Image icon32 = new Image(display, is32);
is32.close();
InputStream is48 = loader.getResourceAsStream(
"org/intrace/icons/intrace48.gif");
Image icon48 = new Image(display, is48);
is48.close();
InputStream is128 = loader.getResourceAsStream(
"org/intrace/icons/intrace128.png");
Image icon128 = new Image(display, is128);
is128.close();
return new Image[] {icon16, icon32, icon48, icon128};
}
}