diff --git a/intrace.ecl.plugin/icons/intrace-editor.gif b/intrace.ecl.plugin/icons/intrace-editor.gif index 09cab8c..598f54f 100644 Binary files a/intrace.ecl.plugin/icons/intrace-editor.gif and b/intrace.ecl.plugin/icons/intrace-editor.gif differ diff --git a/intrace.ecl.plugin/lib/intrace-agent.jar b/intrace.ecl.plugin/lib/intrace-agent.jar index 0bcbc5b..15bd200 100644 Binary files a/intrace.ecl.plugin/lib/intrace-agent.jar and b/intrace.ecl.plugin/lib/intrace-agent.jar differ diff --git a/intrace.ecl.plugin/lib/intrace-ui-helper.jar b/intrace.ecl.plugin/lib/intrace-ui-helper.jar index 0778ed7..601e4d5 100644 Binary files a/intrace.ecl.plugin/lib/intrace-ui-helper.jar and b/intrace.ecl.plugin/lib/intrace-ui-helper.jar differ diff --git a/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ConfigurationDelegate.java b/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ConfigurationDelegate.java index 834e802..b2d44f6 100644 --- a/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ConfigurationDelegate.java +++ b/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ConfigurationDelegate.java @@ -3,9 +3,13 @@ package intrace.ecl.ui.launching; import intrace.ecl.Activator; import intrace.ecl.Util; import intrace.ecl.ui.output.EditorInput; +import intrace.ecl.ui.output.EditorInput.InputType; import java.io.IOException; import java.net.ServerSocket; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; @@ -31,6 +35,11 @@ import org.eclipse.ui.ide.IDE; public class ConfigurationDelegate extends AbstractJavaLaunchConfigurationDelegate implements IExecutableExtension { + public static final String INTRACE_LAUNCHKEY = "INTRACE_LAUNCHKEY"; + public static final Map intraceConnections = new ConcurrentHashMap(); + private static final AtomicLong intraceConnectionId = new AtomicLong(); + + protected String launchtype; protected ILaunchConfigurationDelegate launchdelegate; @@ -65,13 +74,18 @@ public class ConfigurationDelegate extends AbstractJavaLaunchConfigurationDelega { try { + // Create working copy + ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy(); + // Prepare callback server socket ServerSocket callbackServer = new ServerSocket(0); final ConnectionHolder callback = new ConnectionHolder(callbackServer); - callback.start(); + callback.start(); + long connId = intraceConnectionId.getAndIncrement(); + intraceConnections.put(connId, callback); + wc.setAttribute(INTRACE_LAUNCHKEY, Long.toString(connId)); - // Add VM arguments - ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy(); + // Add VM arguments String vmArgs = wc.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, ""); if (Activator.getDefault().agentArg.length() > 0) { @@ -94,7 +108,8 @@ public class ConfigurationDelegate extends AbstractJavaLaunchConfigurationDelega { IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); IWorkbenchPage page = window.getActivePage(); - IDE.openEditor(page, new EditorInput(callback), "intrace.ecl.plugin.ui.output.inTraceEditor"); + IDE.openEditor(page, new EditorInput(callback, InputType.NEWCONNECTION), + "intrace.ecl.plugin.ui.output.inTraceEditor"); } catch (PartInitException e) { diff --git a/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ConnectionHolder.java b/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ConnectionHolder.java index 44e5eb5..90d132f 100644 --- a/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ConnectionHolder.java +++ b/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ConnectionHolder.java @@ -12,7 +12,7 @@ public class ConnectionHolder implements Runnable { private final ServerSocket server; private Socket clientConnection = null; - private String agentServerPort = null; + public String agentServerPort = null; public ConnectionHolder(ServerSocket xiServer) { @@ -38,7 +38,6 @@ public class ConnectionHolder implements Runnable { Map settingsMap = (Map)obj; agentServerPort = settingsMap.get(AgentConfigConstants.SERVER_PORT); - System.out.println("Detected agent server port: " + agentServerPort); } // Notify the UI that we have the connection diff --git a/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ShowInTraceOutputAction.java b/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ShowInTraceOutputAction.java index f6df346..9a57e70 100644 --- a/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ShowInTraceOutputAction.java +++ b/intrace.ecl.plugin/src/intrace/ecl/ui/launching/ShowInTraceOutputAction.java @@ -1,52 +1,452 @@ package intrace.ecl.ui.launching; +import intrace.ecl.ui.output.EditorInput; +import intrace.ecl.ui.output.EditorInput.InputType; + +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.model.IDebugElement; +import org.eclipse.debug.core.model.IProcess; +import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.ui.IActionDelegate2; import org.eclipse.ui.IViewActionDelegate; import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE; -public class ShowInTraceOutputAction implements IViewActionDelegate, IActionDelegate2 +public class ShowInTraceOutputAction implements IViewActionDelegate, + IActionDelegate2 { - + /** + * The underlying action for this delegate + */ + private IAction fAction; + /** + * This action's view part, or null if not installed in a view. + */ + private IViewPart fViewPart; + + /** + * Cache of the most recent selection + */ + private IStructuredSelection fSelection = StructuredSelection.EMPTY; + + /** + * Whether this delegate has been initialized + */ + private boolean fInitialized = false; + @Override public void run(IAction action) { - // TODO Auto-generated method stub - + if (action.isEnabled()) + { + IStructuredSelection selection = getSelection(); + // disable the action so it cannot be run again until an event or + // selection change + // updates the enablement + action.setEnabled(false); + runInForeground(selection); + } } - @Override - public void selectionChanged(IAction action, ISelection selection) + /** + * Runs this action in the UI thread. + */ + private void runInForeground(final IStructuredSelection selection) { - action.setEnabled(true); + // final MultiStatus status= + // new MultiStatus(DebugUIPlugin.getUniqueIdentifier(), + // DebugException.REQUEST_FAILED, getStatusMessage(), null); + BusyIndicator.showWhile(Display.getCurrent(), new Runnable() + { + public void run() + { + Iterator selectionIter = selection.iterator(); + while (selectionIter.hasNext()) + { + Object element = selectionIter.next(); + try + { + // Action's enablement could have been changed since + // it was last enabled. Check that the action is still + // enabled before running the action. + if (isEnabledFor(element)) + doAction(element); + } + catch (Exception e) + { + // status.merge(e.getStatus()); + e.printStackTrace(); + } + } + } + }); + // reportErrors(status); } - @Override - public void init(IAction action) + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action + * .IAction, org.eclipse.jface.viewers.ISelection) + */ + public void selectionChanged(IAction action, ISelection s) { - action.setEnabled(true); + boolean wasInitialized = initialize(action, s); + if (!wasInitialized) + { + if (getView() != null) + { + update(action, s); + } + } + } + + /** + * Updates the specified selection based on the selection, as well as setting + * the selection for this action + * + * @param action + * the action to update + * @param s + * the selection + */ + protected void update(IAction action, ISelection s) + { + if (s instanceof IStructuredSelection) + { + IStructuredSelection ss = getTargetSelection((IStructuredSelection) s); + action.setEnabled(getEnableStateForSelection(ss)); + setSelection(ss); + } + else + { + action.setEnabled(false); + setSelection(StructuredSelection.EMPTY); + } + } + + protected void doAction(Object object) + { + ILaunch launch = getLaunch(object); + if (launch != null) + { + // Get connection object + String connIDStr; + try + { + connIDStr = launch.getLaunchConfiguration().getAttribute(ConfigurationDelegate.INTRACE_LAUNCHKEY, ""); + Long connID = Long.parseLong(connIDStr); + final ConnectionHolder conn = ConfigurationDelegate.intraceConnections.get(connID); + + // Launch editor + final IWorkbench workbench = PlatformUI.getWorkbench(); + Display display = workbench.getDisplay(); + display.asyncExec(new Runnable() + { + @Override + public void run() + { + try + { + IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + IWorkbenchPage page = window.getActivePage(); + IDE.openEditor(page, new EditorInput(conn, InputType.RECONNECT), + "intrace.ecl.plugin.ui.output.inTraceEditor"); + } + catch (PartInitException e) + { + e.printStackTrace(); + } + } + }); + } + catch (CoreException e1) + { + e1.printStackTrace(); + } + } } @Override public void dispose() { - // TODO Auto-generated method stub - + fSelection = null; } - @Override - public void runWithEvent(IAction action, Event event) - { - // TODO Auto-generated method stub - - } - - @Override + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart) + */ public void init(IViewPart view) { - // TODO Auto-generated method stub - + fViewPart = view; } + + /** + * Returns this action's view part, or null if not installed in a + * view. + * + * @return view part or null + */ + protected IViewPart getView() + { + return fViewPart; + } + + /** + * Initialize this delegate, updating this delegate's presentation. As well, + * all of the flavors of AbstractDebugActionDelegates need to have the initial + * enabled state set with a call to update(IAction, ISelection). + * + * @param action + * the presentation for this action + * @return whether the action was initialized + */ + protected boolean initialize(IAction action, ISelection selection) + { + if (!isInitialized()) + { + setAction(action); + update(action, selection); + setInitialized(true); + return true; + } + return false; + } + + /** + * Returns the most recent selection + * + * @return structured selection + */ + protected IStructuredSelection getSelection() + { + return fSelection; + } + + /** + * Sets the most recent selection + * + * @parm selection structured selection + */ + private void setSelection(IStructuredSelection selection) + { + fSelection = selection; + } + + /** + * Allows the underlying IAction to be set to the specified + * IAction + * + * @param action + * the action to set + */ + protected void setAction(IAction action) + { + fAction = action; + } + + /** + * Allows access to the underlying IAction + * + * @return the underlying IAction + */ + protected IAction getAction() + { + return fAction; + } + + /** + * Returns if this action has been initialized or not + * + * @return if this action has been initialized or not + */ + protected boolean isInitialized() + { + return fInitialized; + } + + /** + * Sets the initialized state of this action to the specified boolean value + * + * @param initialized + * the value to set the initialized state to + */ + protected void setInitialized(boolean initialized) + { + fInitialized = initialized; + } + + /** + * Return whether the action should be enabled or not based on the given + * selection. + */ + protected boolean getEnableStateForSelection(IStructuredSelection selection) + { + if (selection.size() == 0) + { + return false; + } + Iterator itr = selection.iterator(); + while (itr.hasNext()) + { + Object element = itr.next(); + if (!isEnabledFor(element)) + { + return false; + } + } + return true; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.IActionDelegate2#runWithEvent(org.eclipse.jface.action.IAction + * , org.eclipse.swt.widgets.Event) + */ + public void runWithEvent(IAction action, Event event) + { + run(action); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IActionDelegate2#init(org.eclipse.jface.action.IAction) + */ + public void init(IAction action) + { + fAction = action; + } + + /** + * Return the ILaunch associated with a model element, or null if there is no + * such association. + * + * @param element + * the model element + * @return the ILaunch associated with the element, or null. + * @since 3.6 + */ + private static ILaunch getLaunch(Object element) + { + // support for custom models + ILaunch launch = (ILaunch) DebugPlugin.getAdapter(element, ILaunch.class); + if (launch == null) + { + // support for standard debug model + if (element instanceof IDebugElement) + { + launch = ((IDebugElement) element).getLaunch(); + } + else if (element instanceof ILaunch) + { + launch = ((ILaunch) element); + } + else if (element instanceof IProcess) + { + launch = ((IProcess) element).getLaunch(); + } + } + return launch; + } + + /** + * Returns whether the given launch configuration should be visible in the + * debug ui. If the config is marked as private, or belongs to a different + * category (i.e. non-null), then this configuration should not be displayed + * in the debug ui. + * + * @param launchConfiguration + * @return boolean + */ + private static boolean isVisible(ILaunchConfiguration launchConfiguration) + { + try + { + return !(launchConfiguration.getAttribute(IDebugUIConstants.ATTR_PRIVATE, + false)); + } + catch (CoreException e) + { + } + return false; + } + + protected boolean isEnabledFor(Object element) + { + ILaunch launch = getLaunch(element); + return launch != null && launch.getLaunchConfiguration() != null + && isVisible(launch.getLaunchConfiguration()) && + connAvailable(launch.getLaunchConfiguration()); + } + + private static boolean connAvailable(ILaunchConfiguration launchConfiguration) + { + try + { + String connID = launchConfiguration.getAttribute(ConfigurationDelegate.INTRACE_LAUNCHKEY, ""); + if (connID.length() > 0) + { + return true; + } + } + catch (CoreException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return false; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.internal.ui.actions.AbstractDebugActionDelegate# + * getTargetSelection(org.eclipse.jface.viewers.IStructuredSelection) + */ + protected IStructuredSelection getTargetSelection(IStructuredSelection s) + { + if (s.isEmpty()) + { + return s; + } + Set dups = new LinkedHashSet(); + Iterator iterator = s.iterator(); + while (iterator.hasNext()) + { + Object object = iterator.next(); + ILaunch launch = getLaunch(object); + if (launch == null) + { + return s; + } + dups.add(launch); + } + return new StructuredSelection(dups.toArray()); + } + } diff --git a/intrace.ecl.plugin/src/intrace/ecl/ui/output/EditorInput.java b/intrace.ecl.plugin/src/intrace/ecl/ui/output/EditorInput.java index 2913725..64ff7e9 100644 --- a/intrace.ecl.plugin/src/intrace/ecl/ui/output/EditorInput.java +++ b/intrace.ecl.plugin/src/intrace/ecl/ui/output/EditorInput.java @@ -9,10 +9,18 @@ import org.eclipse.ui.IPersistableElement; public class EditorInput implements IEditorInput { public final ConnectionHolder callback; + public final InputType type; + + public enum InputType + { + NEWCONNECTION, + RECONNECT + } - public EditorInput(ConnectionHolder xiCallback) + public EditorInput(ConnectionHolder xiCallback, InputType xiType) { this.callback = xiCallback; + this.type = xiType; } @SuppressWarnings("rawtypes") diff --git a/intrace.ecl.plugin/src/intrace/ecl/ui/output/InTraceEditor.java b/intrace.ecl.plugin/src/intrace/ecl/ui/output/InTraceEditor.java index 19e971e..a0930b4 100644 --- a/intrace.ecl.plugin/src/intrace/ecl/ui/output/InTraceEditor.java +++ b/intrace.ecl.plugin/src/intrace/ecl/ui/output/InTraceEditor.java @@ -1,5 +1,7 @@ package intrace.ecl.ui.output; +import intrace.ecl.ui.output.EditorInput.InputType; + import java.net.Socket; import org.eclipse.core.runtime.IProgressMonitor; @@ -53,22 +55,29 @@ public class InTraceEditor extends EditorPart }); inTraceUI.setConnectionState(ConnectState.CONNECTING); final EditorInput intraceInput = (EditorInput)getEditorInput(); - new Thread(new Runnable() - { - @Override - public void run() - { - try - { - Socket connection = intraceInput.callback.getClientConnection(); - inTraceUI.setFixedLocalConnection(connection); - } - catch (InterruptedException e) + if (intraceInput.type == InputType.NEWCONNECTION) + { + new Thread(new Runnable() + { + @Override + public void run() { - e.printStackTrace(); - } - } - }).start(); + try + { + Socket connection = intraceInput.callback.getClientConnection(); + inTraceUI.setFixedLocalConnection(connection); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + }).start(); + } + else + { + inTraceUI.setFixedLocalConnection(intraceInput.callback.agentServerPort); + } } @Override diff --git a/org.intrace/src/org/intrace/client/gui/helper/InTraceUI.java b/org.intrace/src/org/intrace/client/gui/helper/InTraceUI.java index 7cdc5de..e9a13e3 100644 --- a/org.intrace/src/org/intrace/client/gui/helper/InTraceUI.java +++ b/org.intrace/src/org/intrace/client/gui/helper/InTraceUI.java @@ -162,6 +162,30 @@ public class InTraceUI implements ISocketCallback, IControlConnectionListener }); } + public void setFixedLocalConnection(final String xiPort) + { + fixedConnection = true; + if (!sRoot.isDisposed()) + { + sWindow.getDisplay().asyncExec(new Runnable() + { + @Override + public void run() + { + connTab.addressInput.setText("localhost"); + connTab.portInput.setText(xiPort); + textOutputTab.filterThread.addSystemTraceLine("Instructions"); + textOutputTab.filterThread.addSystemTraceLine(" - Select Classes you want to Trace"); + textOutputTab.filterThread.addSystemTraceLine("Full help available on the Help tab"); + textOutputTab.filterThread.addSystemTraceLine(""); + setConnectionState(ConnectState.CONNECTING); + updateUIStateSameThread(); + Connection.connectToAgent(thisWindow, sWindow, "localhost", xiPort); + } + }); + } + } + public void setFixedLocalConnection(final Socket xiSocket) { fixedConnection = true;