package com.dubture.symfony.ui.wizards.importer; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import org.apache.commons.io.FileUtils; import org.eclipse.core.internal.resources.ProjectDescription; import org.eclipse.core.internal.resources.ProjectDescriptionReader; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.dltk.internal.ui.wizards.dialogfields.DialogField; import org.eclipse.dltk.internal.ui.wizards.dialogfields.IDialogFieldListener; import org.eclipse.dltk.internal.ui.wizards.dialogfields.IStringButtonAdapter; import org.eclipse.dltk.internal.ui.wizards.dialogfields.LayoutUtil; import org.eclipse.dltk.internal.ui.wizards.dialogfields.StringButtonDialogField; import org.eclipse.dltk.internal.ui.wizards.dialogfields.StringDialogField; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.php.core.PHPVersion; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.ui.PlatformUI; import org.eclipse.php.composer.api.ComposerPackage; import org.eclipse.php.composer.api.VersionedPackage; import org.eclipse.php.composer.api.collection.Dependencies; import org.eclipse.php.composer.api.json.ParseException; import com.dubture.symfony.core.SymfonyVersion; import com.dubture.symfony.core.log.Logger; import com.dubture.symfony.ui.SymfonyPluginImages; import com.dubture.symfony.ui.SymfonyUiPlugin; /** * @author Robert Gruendler <r.gruendler@gmail.com> */ @SuppressWarnings("restriction") public class SymfonyImportFirstPage extends WizardPage { public class ValidationException extends Exception { private static final long serialVersionUID = 1L; public ValidationException(String string) { super(string); } } private StringButtonDialogField sourceButton; private StringButtonDialogField containerButton; private StringButtonDialogField consoleButton; protected IPath sourcePath; protected IPath consolePath; protected IPath containerPath; protected String projectName; protected PHPVersion phpVersion; protected SymfonyVersion symfonyVersion; private SymfonyProjectScanner scanner; private StringDialogField projectNameField; private IWorkspace workspace; protected SymfonyImportFirstPage(String pageName) { super(pageName); scanner = new SymfonyProjectScanner(); workspace = ResourcesPlugin.getWorkspace(); setTitle("Import Symfony project"); setDescription("Import an existing Symfony project into your workspace"); setImageDescriptor(SymfonyPluginImages.DESC_WIZBAN_IMPORT_PROJECT); } @Override public void createControl(Composite parent) { Composite container = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).applyTo(container); GridDataFactory.fillDefaults().grab(true, true).applyTo(container); projectNameField = new StringDialogField(); projectNameField.setLabelText("Project name"); projectNameField.doFillIntoGrid(container, 3); projectNameField.setDialogFieldListener(new IDialogFieldListener() { @Override public void dialogFieldChanged(DialogField field) { projectName = projectNameField.getText(); validateSettings(); } }); sourceButton = new StringButtonDialogField(new IStringButtonAdapter() { @Override public void changeControlPressed(DialogField field) { try { DirectoryDialog dialog = new DirectoryDialog(getShell()); String result = dialog.open(); if (result != null) { sourceButton.setText(result); sourcePath = new Path(result); enableButtons(); scanSourceFolder(); } } catch (Exception e) { Logger.logException(e); } } }); sourceButton.setButtonLabel("Browse"); sourceButton.setLabelText("Source folder"); sourceButton.doFillIntoGrid(container, 3); sourceButton.getTextControl(null).setEnabled(false); containerButton = new StringButtonDialogField(new IStringButtonAdapter() { @Override public void changeControlPressed(DialogField field) { try { FileDialog dialog = new FileDialog(getShell()); //dialog.setFilterExtensions(new String[]{"xml"}); String result = dialog.open(); String relativePath = getRelativePath(result); if (result != null && relativePath != null) { containerButton.setText(relativePath); containerPath= new Path(relativePath); validateSettings(); } } catch (Exception e) { Logger.logException(e); } } }); LayoutUtil.setHorizontalGrabbing(sourceButton.getTextControl(null)); containerButton.setButtonLabel("Browse"); containerButton.setLabelText("Dumped container"); containerButton.doFillIntoGrid(container, 3); consoleButton = new StringButtonDialogField(new IStringButtonAdapter() { @Override public void changeControlPressed(DialogField field) { FileDialog dialog = new FileDialog(getShell()); String result = dialog.open(); String relativePath = getRelativePath(result); if (result != null && relativePath != null) { consoleButton.setText(relativePath); consolePath = new Path(relativePath); validateSettings(); } } }); LayoutUtil.setHorizontalGrabbing(containerButton.getTextControl(null)); consoleButton.setButtonLabel("Browse"); consoleButton.setLabelText("Symfony console"); consoleButton.doFillIntoGrid(container, 3); LayoutUtil.setHorizontalGrabbing(consoleButton.getTextControl(null)); PlatformUI.getWorkbench().getHelpSystem().setHelp(container, SymfonyUiPlugin.PLUGIN_ID + "." + "import_firstpage"); disableButtons(); setControl(container); } protected String getRelativePath(String path) { if (path == null) { return null; } IPath container = new Path(path); if (!sourcePath.isPrefixOf(container)) { return null; } return container.setDevice(null).removeFirstSegments(sourcePath.segmentCount()).toOSString(); } protected void enableButtons() { consoleButton.setEnabled(true); consoleButton.getTextControl(null).setEnabled(false); containerButton.setEnabled(true); containerButton.getTextControl(null).setEnabled(false); } protected void disableButtons() { consoleButton.setEnabled(false); containerButton.setEnabled(false); } protected void scanSourceFolder() throws InvocationTargetException, InterruptedException { if (sourcePath == null) { return; } getWizard().getContainer().run(true, true, scanner); if (scanner.getConsole() != null && scanner.getConsole().exists()) { IPath newConsolePath = new Path(scanner.getConsole().getAbsolutePath()); newConsolePath = newConsolePath.removeFirstSegments(sourcePath.segmentCount()); consoleButton.setText(newConsolePath.setDevice(null).toOSString()); consolePath = newConsolePath; } if (scanner.getContainer() != null && scanner.getContainer().exists()) { IPath newContainerPath = new Path(scanner.getContainer().getAbsolutePath()); newContainerPath = newContainerPath.setDevice(null).removeFirstSegments(sourcePath.segmentCount()); containerButton.setText(newContainerPath.toOSString()); containerPath = newContainerPath; } validateSettings(); } protected class SymfonyProjectScanner implements IRunnableWithProgress { private File dumpedContainer; private File console; @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { monitor.beginTask("Scanning Symfony project", 4); scanForDumpedContainer(); monitor.worked(1); scanForConsole(); monitor.worked(1); scanVersions(); monitor.worked(1); scanForExistingProjectFile(); monitor.worked(1); } catch (Exception e) { Logger.logException(e); } finally { monitor.done(); } } protected void scanForDumpedContainer() { String sourcePath = sourceButton.getText(); File sourceDirectory = new File(sourcePath); Collection<File> files = FileUtils.listFiles(sourceDirectory, null, true); for (File file : files) { if (file.getName().toLowerCase().endsWith("container.xml")) { dumpedContainer = file; break; } } } protected void scanForConsole() { String sourcePath = sourceButton.getText(); File sourceDirectory = new File(sourcePath); Collection<File> files = FileUtils.listFiles(sourceDirectory, null, true); for (File file : files) { if (file.getName().toLowerCase().equals("console")) { console = file; break; } } } protected void scanVersions() throws IOException, ParseException { IPath composerPath = sourcePath.append("composer.json"); ComposerPackage composer = new ComposerPackage(composerPath.toFile()); Dependencies require = composer.getRequire(); for (VersionedPackage versioned: require) { if ("symfony/symfony".equals(versioned.getName())) { if (versioned.getVersion().startsWith("2.1")) { symfonyVersion = SymfonyVersion.Symfony2_1_9; } else { symfonyVersion = SymfonyVersion.Symfony2_2_1; } } if ("php".equals(versioned.getName())) { if (versioned.getVersion().contains("5.3")) { phpVersion = PHPVersion.PHP5_3; } else { phpVersion = PHPVersion.PHP5_4; } } } } protected void scanForExistingProjectFile() throws IOException { IPath projectPath = sourcePath.append(".project"); if (projectPath.toFile().exists()) { ProjectDescriptionReader reader = new ProjectDescriptionReader(); final ProjectDescription projectDescription = reader.read(projectPath); if (projectDescription != null && projectDescription.getName() != null) { getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { projectName = projectDescription.getName(); projectNameField.setTextWithoutUpdate(projectName); } }); } } } public File getConsole() { return console; } public File getContainer() { return dumpedContainer; } } public IPath getSourcePath() { return sourcePath; } public IPath getContainerPath() { return containerPath; } public IPath getConsolePath() { return consolePath; } public String getProjectName() { return projectName; } public PHPVersion getPHPVersion() { return phpVersion; } public SymfonyVersion getSymfonyVersion() { return symfonyVersion; } public void validateProjectName() throws ValidationException { try { IProject project = workspace.getRoot().getProject(projectName); if (project != null && project.exists()) { throw new ValidationException("A project with the same name already exists in the workspace."); } } catch (Exception e) { throw new ValidationException(e.getMessage()); } } public void validateContainerPath() throws ValidationException { try { validatePath(containerPath.toOSString()); } catch (Exception e) { throw new ValidationException("The selected service container does not exist."); } } public void validateConsolePath() throws ValidationException { try { validatePath(consolePath.toOSString()); } catch (Exception e) { throw new ValidationException("The selected Symfony console does not exist."); } } public void validatePath(String path) throws ValidationException { if (sourcePath == null) { throw new ValidationException(""); } File absolute = new File(sourcePath.toOSString(), path); if (absolute.exists() == false) { throw new ValidationException(""); } } public void validateSettings() { try { validateProjectName(); validateContainerPath(); } catch (ValidationException e) { setErrorMessage(e.getMessage()); setPageComplete(false); return; } setPageComplete(true); setErrorMessage(null); } }