/******************************************************************************* * Copyright (c) 2004,2017 Red Hat, Inc. * 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: * Keith Seitz <keiths@redhat.com> - initial API and implementation * Kent Sebastian <ksebasti@redhat.com> - *******************************************************************************/ package org.eclipse.linuxtools.internal.oprofile.launch.configuration; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.linuxtools.internal.oprofile.core.Oprofile; import org.eclipse.linuxtools.internal.oprofile.core.Oprofile.OprofileProject; import org.eclipse.linuxtools.internal.oprofile.core.daemon.OprofileDaemonOptions; import org.eclipse.linuxtools.internal.oprofile.launch.OprofileLaunchMessages; import org.eclipse.linuxtools.internal.oprofile.launch.OprofileLaunchPlugin; import org.eclipse.linuxtools.profiling.launch.IRemoteFileProxy; import org.eclipse.linuxtools.profiling.launch.RemoteProxyManager; import org.eclipse.linuxtools.tools.launch.core.factory.RuntimeProcessFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.Text; /** * This tab is used by the launcher to configure global oprofile run options. */ public class OprofileSetupTab extends AbstractLaunchConfigurationTab { protected Text kernelImageFileText; protected CCombo controlCombo; protected Button checkSeparateLibrary; protected Button checkSeparateKernel; protected LaunchOptions options = null; protected Spinner executionsSpinner; protected Label executionsSpinnerLabel; private IRemoteFileProxy proxy; protected Label kernelLabel; @Override public String getName() { return OprofileLaunchMessages.getString("tab.global.name"); //$NON-NLS-1$ } @Override public boolean isValid(ILaunchConfiguration config) { return options.isValid(); } @Override public void performApply(ILaunchConfigurationWorkingCopy config) { options.saveConfiguration(config); } @Override public void initializeFrom(ILaunchConfiguration config) { String name = ""; //$NON-NLS-1$ /* * Update the global OprofileProject object. In many occasions its * value is read, which may produce inconsistencies if it is not * up-to-date. */ try { name = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$ if (!name.isEmpty()) { IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name); Oprofile.OprofileProject.setProject(project); } } catch (CoreException e) { // Nothing to do } options.loadConfiguration(config); controlCombo.setText(options.getOprofileComboText()); kernelImageFileText.setText(options.getKernelImageFile()); executionsSpinner.setSelection(options.getExecutionsNumber()); int separate = options.getSeparateSamples(); if (separate == OprofileDaemonOptions.SEPARATE_NONE) { checkSeparateLibrary.setSelection(false); checkSeparateKernel.setSelection(false); } else { //note that opcontrol will nicely ignore the trailing comma if ((separate & OprofileDaemonOptions.SEPARATE_LIBRARY) != 0) checkSeparateLibrary.setSelection(true); if ((separate & OprofileDaemonOptions.SEPARATE_KERNEL) != 0) checkSeparateKernel.setSelection(true); } enableOptionWidgets(); } @Override public void setDefaults(ILaunchConfigurationWorkingCopy config) { options = new LaunchOptions(); options.saveConfiguration(config); } @Override public Image getImage() { return OprofileLaunchPlugin.getImageDescriptor(OprofileLaunchPlugin.ICON_GLOBAL_TAB).createImage(); } @Override public void createControl(Composite parent) { options = new LaunchOptions(); Composite top = new Composite(parent, SWT.NONE); setControl(top); top.setLayout(new GridLayout()); GridData data; GridLayout layout; createVerticalSpacer(top, 1); // Create container for kernel image file selection Composite p = new Composite(top, SWT.NONE); layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; p.setLayout(layout); data = new GridData(GridData.FILL_HORIZONTAL); p.setLayoutData(data); Label l2 = new Label(p, SWT.NONE); l2.setText(OprofileLaunchMessages.getString("tab.global.select")); //$NON-NLS-1$ data = new GridData(); data.horizontalSpan = 2; l2.setLayoutData(data); controlCombo = new CCombo(p, SWT.DROP_DOWN|SWT.READ_ONLY|SWT.BORDER); List<String> tools = new ArrayList<>(Arrays.asList(OprofileProject.OPERF_BINARY)); /* * Check if tools are installed. Use whichComand() method from * RuntimeProcessFactory as it considers the LinuxTools Path. */ IProject project = getOprofileProject(); try { String toolPath = RuntimeProcessFactory.getFactory().whichCommand(OprofileProject.OCOUNT_BINARY, project); // Command found if (!toolPath.equals(OprofileProject.OCOUNT_BINARY)) { tools.add(OprofileProject.OCOUNT_BINARY); } } catch (Exception e) { } controlCombo.setItems(tools.toArray(new String [0])); controlCombo.select(0); controlCombo.addModifyListener(mev -> { OprofileProject.setProfilingBinary(controlCombo.getText()); options.setOprofileComboText(controlCombo.getText()); enableOptionWidgets(); updateLaunchConfigurationDialog(); }); data = new GridData(); data.horizontalSpan = 2; controlCombo.setLayoutData(data); kernelLabel = new Label(p, SWT.NONE); kernelLabel.setText(OprofileLaunchMessages.getString("tab.global.kernelImage.label.text")); //$NON-NLS-1$ kernelLabel.setEnabled(false); data = new GridData(); data.horizontalSpan = 2; kernelLabel.setLayoutData(data); kernelImageFileText = new Text(p, SWT.SINGLE | SWT.BORDER); data = new GridData(GridData.FILL_HORIZONTAL); kernelImageFileText.setLayoutData(data); kernelImageFileText.addModifyListener(mev -> handleKernelImageFileTextModify(kernelImageFileText)); Button button = createPushButton(p, OprofileLaunchMessages.getString("tab.global.kernelImage.browse.button.text"), null); //$NON-NLS-1$ final Shell shell = top.getShell(); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent sev) { showFileDialog(shell); } }); createVerticalSpacer(top, 1); // Create checkbox options container p = new Composite(top, SWT.NONE); layout = new GridLayout(); layout.numColumns = 1; layout.marginHeight = 0; layout.marginWidth = 0; p.setLayout(layout); data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = 2; p.setLayoutData(data); checkSeparateLibrary = myCreateCheckButton(p, OprofileLaunchMessages.getString("tab.global.check.separateLibrary.text")); //$NON-NLS-1$ checkSeparateKernel = myCreateCheckButton(p, OprofileLaunchMessages.getString("tab.global.check.separateKernel.text")); //$NON-NLS-1$ //Number of executions spinner Composite executionsComposite = new Composite(top, SWT.NONE); GridLayout gridLayout = new GridLayout(2, false); executionsComposite.setLayout(gridLayout); executionsSpinnerLabel = new Label(executionsComposite, SWT.LEFT); executionsSpinnerLabel.setText(OprofileLaunchMessages.getString("tab.global.executionsNumber.label.text")); //$NON-NLS-1$ executionsSpinnerLabel.setToolTipText(OprofileLaunchMessages.getString("tab.global.executionsNumber.label.tooltip")); //$NON-NLS-1$ executionsSpinner = new Spinner(executionsComposite, SWT.BORDER); executionsSpinner.setMinimum(1); executionsSpinner.addModifyListener(e -> { options.setExecutionsNumber(executionsSpinner.getSelection()); updateLaunchConfigurationDialog(); }); } // convenience method to create radio buttons with the given label private Button myCreateCheckButton(Composite parent, String label) { final Button b = new Button(parent, SWT.CHECK); b.setText(label); b.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent se) { handleCheckSelected(b); } }); return b; } //sets the proper separation mask for sample separation private void handleCheckSelected(Button button) { int oldSeparate = options.getSeparateSamples(); int newSeparate = oldSeparate; //initalize if (button == checkSeparateLibrary) { if (button.getSelection()) { newSeparate = oldSeparate | OprofileDaemonOptions.SEPARATE_LIBRARY; } else { newSeparate = oldSeparate & ~OprofileDaemonOptions.SEPARATE_LIBRARY; } } else if (button == checkSeparateKernel) { if (button.getSelection()) { newSeparate = oldSeparate | OprofileDaemonOptions.SEPARATE_KERNEL; } else { newSeparate = oldSeparate & ~OprofileDaemonOptions.SEPARATE_KERNEL; } } options.setSeparateSamples(newSeparate); updateLaunchConfigurationDialog(); } // handles text modification events for all text boxes in this tab private void handleKernelImageFileTextModify(Text text) { String errorMessage = null; String filename = text.getText(); if (filename.length() > 0) { try { proxy = RemoteProxyManager.getInstance().getFileProxy(getOprofileProject()); } catch (CoreException e) { e.printStackTrace(); } IFileStore fileStore = proxy.getResource(filename); if (!fileStore.fetchInfo().exists() || fileStore.fetchInfo().isDirectory()){ String msg = OprofileLaunchMessages.getString("tab.global.kernelImage.kernel.nonexistent"); //$NON-NLS-1$ Object[] args = new Object[] { filename }; errorMessage = MessageFormat.format(msg, args); } //seems odd, but must set it even if it is invalid so that performApply // and isValid work properly options.setKernelImageFile(filename); } else { // no kernel image file options.setKernelImageFile(""); //$NON-NLS-1$ } // Update dialog and error message setErrorMessage(errorMessage); updateLaunchConfigurationDialog(); } // Displays a file dialog to allow the user to select the kernel image file private void showFileDialog(Shell shell) { try { proxy = RemoteProxyManager.getInstance().getFileProxy(getOprofileProject()); } catch (CoreException e) { e.printStackTrace(); } FileDialog d = new FileDialog(shell, SWT.OPEN); IFileStore kernel = proxy.getResource(options.getKernelImageFile()); if (!kernel.fetchInfo().exists()) { kernel = proxy.getResource("/boot"); //$NON-NLS-1$ if (!kernel.fetchInfo().exists()) { kernel = proxy.getResource("/"); //$NON-NLS-1$ } } d.setFileName(kernel.toString()); d.setText(OprofileLaunchMessages.getString("tab.global.selectKernelDialog.text")); //$NON-NLS-1$ String newKernel = d.open(); if (newKernel != null) { kernel = proxy.getResource(newKernel); if (!kernel.fetchInfo().exists()) { MessageBox mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.RETRY | SWT.CANCEL); mb.setMessage(OprofileLaunchMessages.getString("tab.global.selectKernelDialog.error.kernelDoesNotExist.text")); //$NON-NLS-1$ switch (mb.open()) { case SWT.RETRY: // Ok, it's recursive, but it shouldn't matter showFileDialog(shell); break; default: case SWT.CANCEL: break; } } else { kernelImageFileText.setText(newKernel); } } } // Enable/disable widgets options according to the tool selected. private void enableOptionWidgets() { if (controlCombo.getText().equals(OprofileProject.OCOUNT_BINARY)) { checkSeparateLibrary.setEnabled(false); checkSeparateKernel.setEnabled(false); kernelImageFileText.setEnabled(false); kernelLabel.setEnabled(false); executionsSpinnerLabel.setEnabled(false); executionsSpinner.setEnabled(false); } else { checkSeparateLibrary.setEnabled(false); checkSeparateKernel.setEnabled(false); kernelImageFileText.setEnabled(false); kernelLabel.setEnabled(false); executionsSpinnerLabel.setEnabled(true); executionsSpinner.setEnabled(true); } } /** * Get project to profile * @return IProject project to profile */ protected IProject getOprofileProject(){ return Oprofile.OprofileProject.getProject(); } }