/******************************************************************************* * Copyright (c) 2009 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation * Zend Technologies *******************************************************************************/ package org.eclipse.php.internal.debug.ui.launching; import java.io.File; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.debug.ui.StringVariableSelectionDialog; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.php.core.PHPToolkitUtil; import org.eclipse.php.debug.core.debugger.parameters.IDebugParametersKeys; import org.eclipse.php.internal.core.util.FileUtils; import org.eclipse.php.internal.debug.core.IPHPDebugConstants; import org.eclipse.php.internal.debug.core.PHPRuntime; import org.eclipse.php.internal.debug.core.preferences.PHPexeItem; import org.eclipse.php.internal.debug.core.preferences.PHPexes; import org.eclipse.php.internal.debug.ui.Logger; import org.eclipse.php.internal.debug.ui.PHPDebugUIImages; import org.eclipse.php.internal.debug.ui.PHPDebugUIMessages; import org.eclipse.php.internal.debug.ui.preferences.phps.NewPHPsComboBlock; import org.eclipse.php.internal.ui.IPHPHelpContextIds; import org.eclipse.php.internal.ui.preferences.ScrolledCompositeImpl; import org.eclipse.swt.SWT; import org.eclipse.swt.accessibility.AccessibleAdapter; import org.eclipse.swt.accessibility.AccessibleEvent; 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.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.eclipse.ui.PlatformUI; /** * PHP executable launch tab is a launch configuration tab for the PHP Script * launching. */ @SuppressWarnings("restriction") public class PHPExecutableLaunchTab extends AbstractLaunchConfigurationTab { static private class ControlAccessibleListener extends AccessibleAdapter { private String controlName; ControlAccessibleListener(final String name) { controlName = name; } public void getName(final AccessibleEvent e) { e.result = controlName; } } protected class WidgetListener extends SelectionAdapter implements ModifyListener { public void modifyText(final ModifyEvent e) { updateLaunchConfigurationDialog(); phpsComboBlock.setProject(getFileProject(fileTextField.getText())); } public void widgetSelected(final SelectionEvent e) { setDirty(true); final Object source = e.getSource(); if (source == fileLocationButton) handleFileLocationButtonSelected(); else if (source == argumentVariablesButton) handleChangeFileToDebug(fileTextField); } } // Selection changed listener (checked PHP exe) protected final IPropertyChangeListener fPropertyChangeListener = new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { handleSelectedPHPexeChanged(); } }; protected Text fileTextField; protected Button argumentVariablesButton; protected Text prgmArgumentsText; protected boolean enableFileSelection; protected Button fileLocationButton = null; // XXX: never set protected WidgetListener fListener = new WidgetListener(); protected Text locationField; protected NewPHPsComboBlock phpsComboBlock; protected SelectionAdapter selectionAdapter; public PHPExecutableLaunchTab() { enableFileSelection = true; phpsComboBlock = new NewPHPsComboBlock(); } public void createControl(final Composite parent) { ScrolledCompositeImpl scrolledCompositeImpl = new ScrolledCompositeImpl(parent, SWT.V_SCROLL | SWT.H_SCROLL); final Composite mainComposite = new Composite(scrolledCompositeImpl, SWT.NONE); setControl(scrolledCompositeImpl); mainComposite.setFont(parent.getFont()); final GridLayout layout = new GridLayout(); layout.numColumns = 1; final GridData gridData = new GridData(GridData.FILL_HORIZONTAL); mainComposite.setLayout(layout); mainComposite.setLayoutData(gridData); scrolledCompositeImpl.setContent(mainComposite); scrolledCompositeImpl.setLayout(layout); scrolledCompositeImpl.setFont(parent.getFont()); createLocationComponent(mainComposite); if (enableFileSelection) { createFileSelectionComponent(mainComposite); } createArgumentsComponent(mainComposite); createVerticalSpacer(mainComposite, 1); Dialog.applyDialogFont(parent); // HELP PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IPHPHelpContextIds.LOCALLY_DEBUGGING_A_PHP_SCRIPT); } /* * (non-Javadoc) * * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getImage() */ @Override public Image getImage() { return PHPDebugUIImages.get(PHPDebugUIImages.IMG_OBJ_PHP_EXE_LAUNCH); } /* * (non-Javadoc) * * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName() */ public String getName() { return PHPDebugUIMessages.PHPExecutableLaunchTab_2; } /* * (non-Javadoc) * * @see * org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse * .debug.core.ILaunchConfiguration) */ public void initializeFrom(final ILaunchConfiguration configuration) { if (enableFileSelection) updateArgument(configuration); try { prgmArgumentsText .setText(configuration.getAttribute(IDebugParametersKeys.EXE_CONFIG_PROGRAM_ARGUMENTS, "")); //$NON-NLS-1$ } catch (final CoreException e) { Logger.log(Logger.ERROR, "Error reading configuration", e); //$NON-NLS-1$ } isValid(configuration); updatePHPFromConfig(configuration); } /* * (non-Javadoc) * * @see * org.eclipse.debug.ui.ILaunchConfigurationTab#isValid(org.eclipse.debug * .core.ILaunchConfiguration) */ public boolean isValid(final ILaunchConfiguration launchConfig) { setErrorMessage(null); setWarningMessage(null); try { final String phpExe = launchConfig.getAttribute(IPHPDebugConstants.ATTR_EXECUTABLE_LOCATION, ""); //$NON-NLS-1$ boolean phpExeExists = true; try { final File file = new File(phpExe); if (!file.exists()) phpExeExists = false; } catch (final NullPointerException e) { phpExeExists = false; } if (!phpExeExists) { setErrorMessage(PHPDebugUIMessages.PHP_Location_Message); return false; } if (enableFileSelection) { final String phpFile = launchConfig.getAttribute(IPHPDebugConstants.ATTR_FILE, ""); //$NON-NLS-1$ if (FileUtils.resourceExists(phpFile)) { IResource fileToData = ResourcesPlugin.getWorkspace().getRoot().findMember(phpFile); // check if not a file (project, folder etc.) if ((fileToData.getType() != IResource.FILE) || !PHPToolkitUtil.isPHPFile((IFile) fileToData)) { setErrorMessage(phpFile + PHPDebugUIMessages.PHPExecutableLaunchTab_isNotPHPFile); return false; } } else if (new File(phpFile).exists()) { if (!PHPToolkitUtil.hasPHPExtention(phpFile)) { setErrorMessage(phpFile + PHPDebugUIMessages.PHPExecutableLaunchTab_isNotPHPFile); return false; } } else { // resource DOES NOT exist setErrorMessage(PHPDebugUIMessages.PHP_File_Not_Exist); return false; } } PHPexeItem phpExeItem = phpsComboBlock != null ? phpsComboBlock.getPHPexe() : null; if (phpExeItem == null) { String storedPHPexePath = launchConfig.getAttribute(PHPRuntime.PHP_CONTAINER, (String) null); phpExeItem = storedPHPexePath != null ? PHPRuntime.getPHPexeItem(Path.fromPortableString(storedPHPexePath)) : null; } // Check if script arguments can be passed (CLI SAPI required) String exeProgramArgs = prgmArgumentsText != null ? prgmArgumentsText.getText() : null; if (exeProgramArgs == null) exeProgramArgs = launchConfig.getAttribute(IDebugParametersKeys.EXE_CONFIG_PROGRAM_ARGUMENTS, ""); //$NON-NLS-1$ if (!exeProgramArgs.isEmpty()) { if (phpExeItem != null && !(PHPexeItem.SAPI_CLI.equals(phpExeItem.getSapiType()))) setWarningMessage(PHPDebugUIMessages.PHPExecutableLaunchTab_argumentsWillNotBePassed); } } catch (final CoreException e) { } return true; } /* * (non-Javadoc) * * @see * org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse * .debug.core.ILaunchConfigurationWorkingCopy) */ public void performApply(final ILaunchConfigurationWorkingCopy configuration) { if (phpsComboBlock.isDefaultPHP()) { configuration.setAttribute(PHPRuntime.PHP_CONTAINER, (String) null); } else { IPath containerPath = phpsComboBlock.getPath(); String portablePath = null; if (containerPath != null) { portablePath = containerPath.toPortableString(); } configuration.setAttribute(PHPRuntime.PHP_CONTAINER, portablePath); } // Set the executable path final String selectedExecutable = phpsComboBlock.getSelectedExecutablePath(); if (selectedExecutable.length() == 0) { configuration.setAttribute(IPHPDebugConstants.ATTR_EXECUTABLE_LOCATION, (String) null); } else { configuration.setAttribute(IPHPDebugConstants.ATTR_EXECUTABLE_LOCATION, selectedExecutable); } // Set the PHP ini path final String iniPath = phpsComboBlock.getSelectedIniPath(); if (iniPath.length() == 0) { configuration.setAttribute(IPHPDebugConstants.ATTR_INI_LOCATION, (String) null); } else { configuration.setAttribute(IPHPDebugConstants.ATTR_INI_LOCATION, iniPath); } if (enableFileSelection) { configuration.setAttribute(IPHPDebugConstants.ATTR_FILE, fileTextField.getText().trim()); configuration.setAttribute(IPHPDebugConstants.ATTR_FILE_FULL_PATH, fileTextField.getData().toString().trim()); } String scriptArguments = prgmArgumentsText.getText().trim(); configuration.setAttribute(IDebugParametersKeys.EXE_CONFIG_PROGRAM_ARGUMENTS, scriptArguments.length() > 0 ? scriptArguments : null); } /* * (non-Javadoc) * * @see * org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse. * debug.core.ILaunchConfigurationWorkingCopy) */ public void setDefaults(final ILaunchConfigurationWorkingCopy configuration) { try { String executableLocation = configuration.getAttribute(IPHPDebugConstants.ATTR_EXECUTABLE_LOCATION, ""); //$NON-NLS-1$ if (executableLocation.equals("")) { //$NON-NLS-1$ PHPexes phpExes = PHPexes.getInstance(); final PHPexeItem phpExeItem = phpExes.getDefaultItem(); if (phpExeItem == null) return; executableLocation = phpExeItem.getExecutable().toString(); configuration.setAttribute(IPHPDebugConstants.ATTR_EXECUTABLE_LOCATION, executableLocation); String iniPath = phpExeItem.getINILocation() != null ? phpExeItem.getINILocation().toString() : null; configuration.setAttribute(IPHPDebugConstants.ATTR_INI_LOCATION, iniPath); } configuration.setAttribute(IDebugParametersKeys.EXE_CONFIG_PROGRAM_ARGUMENTS, (String) null); } catch (final CoreException e) { Logger.log(Logger.ERROR, "Error setting default configuration", e); //$NON-NLS-1$ } return; } /* * Fix for Bug 60163 Accessibility: New Builder Dialog missing object info * for textInput controls */ public void addControlAccessibleListener(final Control control, final String controlName) { // strip mnemonic (&) final String[] strs = controlName.split("&"); //$NON-NLS-1$ final StringBuffer stripped = new StringBuffer(); for (String element : strs) stripped.append(element); control.getAccessible().addAccessibleListener(new ControlAccessibleListener(stripped.toString())); } public void setEnableFileSelection(final boolean enabled) { if (enabled == enableFileSelection) return; enableFileSelection = enabled; if (argumentVariablesButton != null) argumentVariablesButton.setVisible(enabled); if (fileTextField != null) fileTextField.setVisible(enabled); } /** * Creates the controls needed to edit the argument and prompt for argument * attributes of an external tool * * @param parent * the composite to create the controls in */ protected void createFileSelectionComponent(final Composite parent) { final Group group = new Group(parent, SWT.NONE); final String groupName = PHPDebugUIMessages.PHP_File; group.setText(groupName); GridLayout layout = new GridLayout(3, false); GridData gd = new GridData(GridData.FILL_HORIZONTAL); group.setLayout(layout); group.setLayoutData(gd); group.setFont(parent.getFont()); fileTextField = new Text(group, SWT.SINGLE | SWT.BORDER); gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; fileTextField.setLayoutData(gd); fileTextField.addModifyListener(fListener); addControlAccessibleListener(fileTextField, group.getText()); fileTextField.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(fileTextField.getText()); String location = ""; //$NON-NLS-1$ if (resource == null) { fileTextField.setData(location); return; } if (resource.getLocation() == null) { location = resource.getFullPath().toString(); } else { location = resource.getLocation().toOSString(); } fileTextField.setData(location); } }); argumentVariablesButton = createPushButton(group, PHPDebugUIMessages.Browse, null); gd = (GridData) argumentVariablesButton.getLayoutData(); gd.horizontalSpan = 1; argumentVariablesButton.addSelectionListener(fListener); // need to strip the mnemonic from buttons addControlAccessibleListener(argumentVariablesButton, argumentVariablesButton.getText()); } /** * Creates the controls needed to edit the location attribute of an external * tool * * @param group * the composite to create the controls in */ protected void createLocationComponent(final Composite parent) { phpsComboBlock.createControl(parent); final Control control = phpsComboBlock.getControl(); if (control instanceof Composite) { Layout layout = ((Composite) control).getLayout(); if (layout instanceof GridLayout) { GridLayout gridLayout = (GridLayout) layout; gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; } } phpsComboBlock.addPropertyChangeListener(fPropertyChangeListener); final GridData gd = new GridData(GridData.FILL_HORIZONTAL); control.setLayoutData(gd); } /** * Creates script arguments group. * * @param parent * parent component */ protected void createArgumentsComponent(final Composite parent) { Group group = new Group(parent, SWT.NONE); group.setLayout(new GridLayout()); group.setLayoutData(new GridData(GridData.FILL_BOTH)); group.setText(PHPDebugUIMessages.PHPExecutableLaunchTab_scriptArguments); prgmArgumentsText = new Text(group, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL); prgmArgumentsText.setLayoutData(new GridData(GridData.FILL_BOTH)); prgmArgumentsText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent evt) { updateLaunchConfigurationDialog(); } }); addControlAccessibleListener(prgmArgumentsText, group.getText()); Button pgrmArgVariableButton = createPushButton(group, PHPDebugUIMessages.PHPExecutableLaunchTab_variables, null); pgrmArgVariableButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); pgrmArgVariableButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(getShell()); dialog.open(); String variable = dialog.getVariableExpression(); if (variable != null) { prgmArgumentsText.insert(variable); prgmArgumentsText.setFont(parent.getFont()); } } }); } /** * Return the String to use as the label for the working directory field. * Subclasses may wish to override. */ protected String getWorkingDirectoryLabel() { return PHPDebugUIMessages.WorkingDirectory; } protected void handleBreakButtonSelected() { updateLaunchConfigurationDialog(); } /** * Prompts the user to choose a location from the filesystem and sets the * location as the full path of the selected file. */ protected void handleFileLocationButtonSelected() { final FileDialog fileDialog = new FileDialog(getShell(), SWT.NONE); fileDialog.setFileName(locationField.getText()); final String text = fileDialog.open(); if (text != null) locationField.setText(text); } protected void handleSelectedPHPexeChanged() { updateLaunchConfigurationDialog(); } /** * A callback method when changing the file to debug via 'Browse' */ protected void handleChangeFileToDebug(final Text textField) { final IResource resource = LaunchUtilities.getFileFromDialog(null, getShell(), LaunchUtil.getFileExtensions(), LaunchUtil.getRequiredNatures(), true); if (resource instanceof IFile) { textField.setText(resource.getFullPath().toString()); String fileLocation = ""; //$NON-NLS-1$ IPath location = resource.getLocation(); if (location != null) { fileLocation = location.toOSString(); } else { fileLocation = resource.getFullPath().toString(); } textField.setData(fileLocation); } } /** * This method updates the jre selection from the * <code>ILaunchConfiguration</code> * * @param config * the config to update from */ protected void updatePHPFromConfig(ILaunchConfiguration config) { try { if (enableFileSelection) { phpsComboBlock.setProject(getFileProject(fileTextField.getText())); } else { phpsComboBlock .setProject(getFileProject(config.getAttribute(IPHPDebugConstants.PHP_Project, (String) null))); } String path = config.getAttribute(PHPRuntime.PHP_CONTAINER, (String) null); phpsComboBlock.setPath(path != null ? Path.fromPortableString(path) : null); } catch (CoreException e) { } } protected IProject getFileProject(String phpFile) { if (FileUtils.resourceExists(phpFile)) { IResource fileToData = ResourcesPlugin.getWorkspace().getRoot().findMember(phpFile); return fileToData.getProject(); } return null; } /** * Updates the argument widgets to match the state of the given launch * configuration. */ protected void updateArgument(final ILaunchConfiguration configuration) { String arguments = ""; //$NON-NLS-1$ String fullPath = ""; //$NON-NLS-1$ try { arguments = configuration.getAttribute(IPHPDebugConstants.ATTR_FILE, ""); //$NON-NLS-1$ fullPath = configuration.getAttribute(IPHPDebugConstants.ATTR_FILE_FULL_PATH, ""); //$NON-NLS-1$ } catch (final CoreException ce) { Logger.log(Logger.ERROR, "Error reading configuration", ce); //$NON-NLS-1$ } if (fileTextField != null) { fileTextField.setText(arguments); fileTextField.setData(fullPath); } } protected boolean isLaunchMode(String mode) { return mode.equals(getLaunchConfigurationDialog().getMode()); } }