/******************************************************************************* * Copyright (c) 2010 Freescale Semiconductor. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Serge Beauchamp (Freescale Semiconductor) - initial API and implementation *******************************************************************************/ package com.freescale.deadlockpreventer.agent.workbench; import java.util.ArrayList; import java.util.Hashtable; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationListener; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.ILaunchesListener2; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.progress.UIJob; import com.freescale.deadlockpreventer.Settings; import com.freescale.deadlockpreventer.agent.IAgent; import com.freescale.deadlockpreventer.agent.IAgent.IProcess; import com.freescale.deadlockpreventer.agent.IConfigurator; public class LaunchConfigurationConfigurator implements IConfigurator{ private static final String DEBUG_PERSPECTIVE = "org.eclipse.debug.ui.DebugPerspective"; private static final String PREF_COMBO_SELECTION = "com.freescale.deadlockpreventer.agent.workbench.comboSelection"; private static final String SPACE = " "; private static final String ORG_ECLIPSE_JDT_LAUNCHING_VM_ARGUMENTS = "org.eclipse.jdt.launching.VM_ARGUMENTS"; private static final String[] supportedLaunchConfigurationTypes = { "org.eclipse.jdt.junit.launchconfig", "org.eclipse.pde.ui.RuntimeWorkbench", "org.eclipse.jdt.launching.localJavaApplication", "org.eclipse.pde.ui.JunitLaunchConfig" }; IAgent agent; private Button launch; private Combo combo; private Hashtable<String, String> oldLaunchSettings = new Hashtable<String, String>(); @Override public void initialize(IAgent agent) { this.agent = agent; ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); manager.addLaunchConfigurationListener(new ILaunchConfigurationListener() { @Override public void launchConfigurationAdded( ILaunchConfiguration configuration) { if (!configuration.isWorkingCopy()) setupComboContentAsync(); } @Override public void launchConfigurationChanged( ILaunchConfiguration configuration) { if (!configuration.isWorkingCopy()) setupComboContentAsync(); } @Override public void launchConfigurationRemoved( ILaunchConfiguration configuration) { if (!configuration.isWorkingCopy()) setupComboContentAsync(); } }); manager.addLaunchListener(new ILaunchesListener2() { @Override public void launchesRemoved(ILaunch[] launches) {} @Override public void launchesAdded(ILaunch[] launches) {} @Override public void launchesChanged(ILaunch[] launches) {} @Override public void launchesTerminated(ILaunch[] launches) { for (ILaunch launch : launches) handleChanged(launch); } }); } protected void setupComboContentAsync() { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { setupComboContent(); } }); } @Override public String getName() { return "Eclipse JDT Debugging"; } @Override public void createPartControl(Composite parent) { parent.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); GridLayout layout = new GridLayout(2, false); parent.setLayout(layout); combo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN); combo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); combo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int index = combo.getSelectionIndex(); if (index != -1 ) agent.setPref(PREF_COMBO_SELECTION, combo.getItem(index)); } }); launch = new Button(parent, SWT.PUSH); launch.setText("Debug"); launch.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); ((GridData)launch.getLayoutData()).widthHint = 80; launch.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { doLaunch(); } }); launch.getShell().setDefaultButton(launch); setupComboContent(); launch.setEnabled(hasAValidLC()); selectOldComboPref(); } private void selectOldComboPref() { String selection = agent.getPref(PREF_COMBO_SELECTION, new String()); if (selection.length() > 0) { String[] items = combo.getItems(); for (int i = 0; i < items.length; i++) { if (items[i].equals(selection)) { combo.select(i); break; } } } } private void setupComboContent() { ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); try { ILaunchConfiguration[] lcs = manager.getLaunchConfigurations(); ArrayList<ILaunchConfiguration> list = new ArrayList<ILaunchConfiguration>(); for (ILaunchConfiguration lc : lcs) { String id = lc.getType().getIdentifier(); for (String type : supportedLaunchConfigurationTypes) { if (id.equals(type)) list.add(lc); } } lcs = list.toArray(new ILaunchConfiguration[0]); String[] strings = new String[lcs.length]; for (int i = 0; i < strings.length; i++) { strings[i] = lcs[i].getName(); } int index = combo.getSelectionIndex(); combo.setItems(strings); if (index == -1 || index > strings.length) { index = strings.length > 0? 0: -1; } combo.select(index); } catch (CoreException e) { e.printStackTrace(); } launch.setEnabled(hasAValidLC()); } private boolean hasAValidLC() { return combo.getSelectionIndex() != -1; } protected void doLaunch() { String name = combo.getItem(combo.getSelectionIndex()); ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); try { ILaunchConfiguration[] lcs = manager.getLaunchConfigurations(); for (ILaunchConfiguration lc : lcs) { if (lc.getName().equals(name)) { doLaunch(lc); break; } } } catch (CoreException e) { e.printStackTrace(); } } private void doLaunch(final ILaunchConfiguration lc) { try { final String attribute = lc.getAttribute(ORG_ECLIPSE_JDT_LAUNCHING_VM_ARGUMENTS, new String()); String[] attributes = attribute.split(SPACE); StringBuffer newAttributes = new StringBuffer(); IProcess process = agent.createProcess(lc.getName()); String prefixAgent = agent.getVMArg(process, IAgent.VM_ARG_AGENT); String prefixBootClassPath = agent.getVMArg(process, IAgent.VM_ARG_BOOT_CLASSPATH); String prefixServerPort = agent.getVMArg(process, IAgent.VM_ARG_BOOT_SERVER_PORT); String prefixAgentPrefix = prefixAgent.split(":")[0]; String prefixBootClassPathPrefix = prefixBootClassPath.split(":")[0]; String prefixServerPortPrefix = prefixServerPort.split("=")[0]; for (String attr : attributes) { if (attr.startsWith(prefixAgentPrefix) || attr.startsWith(prefixBootClassPathPrefix) || attr.startsWith(prefixServerPortPrefix) || attr.contains(Settings.QUERY_SERVICE) || attr.contains(Settings.REPORT_SERVICE)) continue; newAttributes.append(attr + SPACE); } final String cleanedUpAttributes = newAttributes.toString(); newAttributes.append(prefixAgent + SPACE); newAttributes.append(prefixBootClassPath + SPACE); newAttributes.append(prefixServerPort); String additional = agent.getVMArg(process, IAgent.VM_ADDITIONAL_ARGUMENTS); if (additional != null) newAttributes.append(SPACE + additional); newAttributes.append(SPACE + "-D" + Settings.BUNDLE_ADVISOR + "=" + WorkbenchBundleAdvisor.class.getName()); if (Platform.inDebugMode()) System.out.println("adding new vm args to launch conf: " + newAttributes.toString()); ILaunchConfigurationWorkingCopy copy = lc.getWorkingCopy(); copy.setAttribute(ORG_ECLIPSE_JDT_LAUNCHING_VM_ARGUMENTS, newAttributes.toString()); final ILaunchConfiguration newlc = copy.doSave(); oldLaunchSettings.put(newlc.getName(), cleanedUpAttributes); UIJob job = new UIJob("Debugging: " + newlc.getName()) { @Override public IStatus runInUIThread(IProgressMonitor monitor) { try { newlc.launch(ILaunchManager.DEBUG_MODE, monitor); PlatformUI.getWorkbench().showPerspective(DEBUG_PERSPECTIVE, agent.getSite().getWorkbenchWindow()); agent.getSite().getWorkbenchWindow().getActivePage().showView(agent.getViewID()); } catch (CoreException e) { e.printStackTrace(); return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Cannot debug launch configuration: " + newlc.getName()); } return Status.OK_STATUS; } }; job.schedule(); } catch (CoreException e) { e.printStackTrace(); } } protected void handleChanged(ILaunch launch) { if (launch.isTerminated()) { ILaunchConfiguration lc = launch.getLaunchConfiguration(); try { String cleanedUpAttributes = oldLaunchSettings.get(lc.getName()); if (cleanedUpAttributes != null) { ILaunchConfigurationWorkingCopy copy = lc.getWorkingCopy(); copy.setAttribute(ORG_ECLIPSE_JDT_LAUNCHING_VM_ARGUMENTS, cleanedUpAttributes); copy.doSave(); } } catch (CoreException e) { e.printStackTrace(); } } } }