/******************************************************************************* * This file is part of the Symfony eclipse plugin. * * (c) Robert Gruendler <r.gruendler@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. ******************************************************************************/ package com.dubture.symfony.debug.launch; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IProject; 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.dltk.core.DLTKCore; import org.eclipse.dltk.core.IScriptProject; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.fieldassist.AutoCompleteField; import org.eclipse.jface.fieldassist.TextContentAdapter; import org.eclipse.php.internal.debug.core.preferences.PHPDebugCorePreferenceNames; import org.eclipse.php.internal.server.core.Server; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import com.dubture.symfony.core.builder.SymfonyNature; import com.dubture.symfony.core.log.Logger; import com.dubture.symfony.core.model.AppKernel; import com.dubture.symfony.core.model.SymfonyKernelAccess; import com.dubture.symfony.core.model.SymfonyModelAccess; import com.dubture.symfony.debug.DebuggerConfiguration; import com.dubture.symfony.debug.server.SymfonyServer; import com.dubture.symfony.debug.util.ServerUtils; import com.dubture.symfony.index.model.Route; /** * * A Symfony tab for the XDebug Debugger. Adds Environment * and Route selection to the debugger. * * * @author Robert Gruendler <r.gruendler@gmail.com> * */ @SuppressWarnings("restriction") public class LaunchConfigurationTab extends AbstractLaunchConfigurationTab { private Combo kernelCombo; private Text route; private Route currentRoute; private AutoCompleteField ac; private SymfonyModelAccess model = SymfonyModelAccess.getDefault(); private IScriptProject project; private List<AppKernel> kernels; private AppKernel kernel; private boolean isSymfonyDebugger = false; private Composite comp; private ILaunchConfiguration config; private KeyListener routeListener = new KeyListener() { @Override public void keyReleased(KeyEvent e) { if (project == null) return; String prefix = route.getText(); if (prefix.length() < 1) return; List<Route> routes = model.findRoutes(project, prefix); String[] names = new String[routes.size()]; int i=0; for (Route route : routes) { names[i++] = route.getName(); } ac.setProposals(names); } @Override public void keyPressed(KeyEvent e) { } }; private Text url; public LaunchConfigurationTab() { super(); } public boolean isValid(ILaunchConfiguration launchConfig) { setErrorMessage(null); try { if (project == null || project.getProject().hasNature(SymfonyNature.NATURE_ID) == false) return true; } catch (CoreException e) { Logger.logException(e); return true; } if (isSymfonyDebugger == false) return true; String routeName = route.getText(); Route route = model.findRoute(routeName, project); if (route == null) { String message = "The route " + routeName + " does not exist in the project " + project.getElementName(); if (routeName.length() == 0) { message = "You need to set a valid route name for the launch configuration"; } setErrorMessage(message); return false; } try { new URL(url.getText()); } catch (MalformedURLException e) { setMessage("Malformed URL : " + url.getText()); return false; } return true; } @Override public void createControl(Composite parent) { Font font = parent.getFont(); comp = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(1, true); comp.setLayout(layout); comp.setFont(font); GridData gd = new GridData(GridData.FILL_BOTH); comp.setLayoutData(gd); setControl(comp); // setHelpContextId(); Group group = new Group(comp, SWT.NONE); group.setFont(font); layout = new GridLayout(); group.setLayout(layout); group.setLayoutData(new GridData(GridData.FILL_BOTH)); String controlName = "Launch Settings"; group.setText(controlName); Label label = new Label(group, SWT.NONE); label.setText("Environment"); GridData data = new GridData(200, GridData.FILL, true, false); label.setLayoutData(data); kernelCombo = new Combo(group, SWT.READ_ONLY); data = new GridData(); data.horizontalIndent = 0; kernelCombo.setLayoutData(data); kernelCombo.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { for (AppKernel k : kernels) { String env = kernelCombo.getItem(kernelCombo.getSelectionIndex()); if (env.equals(k.getEnvironment())) { kernel = k; break; } } setDirty(true); updateLaunchConfigurationDialog(); updateURL(); } @Override public void widgetDefaultSelected(SelectionEvent e) { } }); Label routeLabel = new Label(group, SWT.NONE); routeLabel.setText("Route"); route = new Text(group, SWT.SINGLE | SWT.BORDER); data = new GridData(); data.widthHint = 200; route.addKeyListener(routeListener); route.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { currentRoute = model.findRoute(route.getText(), project); setDirty(true); updateLaunchConfigurationDialog(); updateURL(); } @Override public void focusGained(FocusEvent e) { } }); route.setLayoutData(data); ac = new AutoCompleteField(route, new TextContentAdapter(), new String[]{}); Label urlLabel = new Label(group, SWT.NONE); urlLabel.setText("Generated URL"); url = new Text(group, SWT.BORDER | SWT.SINGLE); url.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { setDirty(true); updateLaunchConfigurationDialog(); } }); data = new GridData(GridData.FILL, GridData.VERTICAL_ALIGN_BEGINNING, true, false); url.setLayoutData(data); Dialog.applyDialogFont(comp); setControl(comp); } @Override public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { try { String env = configuration.getAttribute(SymfonyServer.ENVIRONMENT, ""); if (env.length() == 0) return; for (int i=0; i<kernelCombo.getItemCount(); i++) { String item = kernelCombo.getItem(i); if (item.equals(env)) kernelCombo.select(i); } } catch (CoreException e) { Logger.logException(e); } } @Override public void initializeFrom(ILaunchConfiguration configuration) { config = configuration; initializeProject(configuration); if (project == null) return; initializeEnvironment(configuration); initializeRoute(configuration); initializeURL(configuration); isValid(configuration); } private void initializeURL(ILaunchConfiguration configuration) { try { String _url = configuration.getAttribute(SymfonyServer.URL, ""); if (_url.length() == 0) { updateURL(); } else { url.setText(_url); } } catch (CoreException e) { Logger.logException(e); } } private void updateURL() { try { if (currentRoute == null) { url.setText(""); return; } String _url = ServerUtils.constructURL(config, project, currentRoute, kernel); url.setText(_url); config.getWorkingCopy().setAttribute(Server.BASE_URL, _url); } catch (CoreException e) { Logger.logException(e); } } private void initializeProject(ILaunchConfiguration configuration) { comp.setEnabled(false); try { String debuggerID = configuration.getAttribute( PHPDebugCorePreferenceNames.PHP_DEBUGGER_ID, ""); isSymfonyDebugger = DebuggerConfiguration.ID.equals(debuggerID); if (isSymfonyDebugger == false) { return; } String file = configuration.getAttribute(Server.FILE_NAME, ""); IPath path = new Path(file); kernels = new ArrayList<AppKernel>(); if (path != null && path.segmentCount() > 0) { IProject rawProject = ResourcesPlugin.getWorkspace().getRoot().getProject(path.removeLastSegments(path.segmentCount()-1).toString()); if (rawProject != null) { project = DLTKCore.create(rawProject); kernels = SymfonyKernelAccess.getDefault().getKernels(project); } } if (project != null && project.getProject().hasNature(SymfonyNature.NATURE_ID)) comp.setEnabled(true); } catch (CoreException e) { // ignore } } private void initializeEnvironment(ILaunchConfiguration configuration) { try { kernelCombo.removeAll(); if (project == null) { comp.setEnabled(false); return; } String env = configuration.getAttribute(SymfonyServer.ENVIRONMENT, ""); comp.setEnabled(true); int i=0; for (AppKernel kernel : kernels) { kernelCombo.add(kernel.getEnvironment()); if (kernel.getEnvironment().equals(env)) { kernelCombo.select(i); this.kernel = kernel; } i++; } } catch (CoreException e) { // ignore } } private void initializeRoute(ILaunchConfiguration configuration) { try { String name = configuration.getAttribute(SymfonyServer.ROUTE, ""); currentRoute = model.findRoute(name, project); route.setText(name); } catch (CoreException e) { } } @Override public void performApply(ILaunchConfigurationWorkingCopy configuration) { try { if (isSymfonyDebugger == false) return; int index = kernelCombo.getSelectionIndex(); if (kernelCombo.getItemCount() > 0 && index >= 0 && index < kernelCombo.getItemCount()) { String env = kernelCombo.getItem(kernelCombo.getSelectionIndex()); configuration.setAttribute(SymfonyServer.ENVIRONMENT, env); } configuration.setAttribute(Server.BASE_URL, url.getText()); configuration.setAttribute(SymfonyServer.URL, url.getText()); String routeName = route.getText(); configuration.setAttribute(SymfonyServer.ROUTE, routeName); } catch (Exception e) { Logger.logException(e); } } @Override public String getName() { return "Symfony"; } }