/******************************************************************************* * Copyright (c) 2012 Pivotal Software, 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: * Pivotal Software, Inc. - initial API and implementation *******************************************************************************/ package org.grails.ide.eclipse.core.wizard; import static org.springsource.ide.eclipse.commons.livexp.core.ValidationResult.error; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.grails.ide.eclipse.commands.GrailsCommandUtils; import org.grails.ide.eclipse.core.GrailsCoreActivator; import org.grails.ide.eclipse.core.internal.GrailsNature; import org.grails.ide.eclipse.core.model.GrailsVersion; import org.grails.ide.eclipse.core.model.IGrailsInstall; import org.springsource.ide.eclipse.commons.livexp.core.CompositeValidator; import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression; import org.springsource.ide.eclipse.commons.livexp.core.LiveVariable; import org.springsource.ide.eclipse.commons.livexp.core.ValidationResult; import org.springsource.ide.eclipse.commons.livexp.core.Validator; import org.springsource.ide.eclipse.commons.livexp.core.ValueListener; /** * Core counterpart of {@link GrailsImportWizard} in the ui plugin. * <p> * Contains code to validate wizard contents and execute the import operation. * It makes use of 'LiveExpressions' to decouple this logic from the wizard's UI. * * @author Kris De Volder */ public class GrailsImportWizardCore { /////////////////////////////////////////////////////////////////////////////////////////// /// "inputs" where the user can enter data /// /// In the UI there will be some widgetry to set the values of these things. /// But this 'core' wizard can also be used in headless mode. Anyone/thing can set the values. public final LiveVariable<File> location = new LiveVariable<File>(null); public final LiveVariable<Boolean> ignoreMavenWarning = new LiveVariable<Boolean>(false); public final LiveVariable<IGrailsInstall> grailsInstall = new LiveVariable<IGrailsInstall>(null); public final LiveVariable<Boolean> copyToWorkspace = new LiveVariable<Boolean>(false); /////////////////////////////////////////////////////////////////////////////////////////// private boolean existsInWorkspace(String name) { if (name!=null) { return ResourcesPlugin.getWorkspace().getRoot().getProject(name).exists(); } return false; } /** * Location is valid if it looks like a Grails project exists at the location. */ public final LiveExpression<ValidationResult> locationValidator = new Validator() { protected ValidationResult compute() { final File rf = location.getValue(); if (rf==null) { return error("Specify the location of a Grails project to import."); } else if (!rf.exists()) { return error("'"+rf+"' doesn't exist."); } else if (!rf.isDirectory()) { return error("'"+rf+"' is not a directory."); } else if (!GrailsNature.looksLikeGrailsProject(rf)) { return error("'"+rf+"' doesn't look like a Grails project"); } else if (existsInWorkspace(rf.getName())) { return error("Project '"+rf.getName()+"' already exists in the workspace."); } return ValidationResult.OK; } } .dependsOn(location); /** * Compute the target location where the imported project should be copied to. * If the option to copy resources into the workspace is not selected this will return null. * It may also return null if other pre-requisites to compute this have not yet been * filled in (e.g. if a project to import has yet to be selected). */ public File getCopyLocation() { if (copyToWorkspace.getValue()) { File loc = location.getValue(); if (loc!=null) { String name = loc.getName(); if (name!=null && !"".equals(name)) { return Platform.getLocation().append(name).toFile(); } } } return null; } public LiveExpression<ValidationResult> copyToWorkspaceValidator = new Validator() { protected ValidationResult compute() { File targetLocation = getCopyLocation(); if (targetLocation!=null && targetLocation.exists()) { return error("Can not copy project into workspace because '"+targetLocation+"' already exists"); } return ValidationResult.OK; } } .dependsOn(copyToWorkspace) .dependsOn(location); public final LiveExpression<Boolean> isMaven = new LiveExpression<Boolean>(false) { @Override protected Boolean compute() { return locationValidator.getValue().isOk() && lookslikeMavenProject(location.getValue()); } } .dependsOn(location) .dependsOn(locationValidator); private boolean lookslikeMavenProject(File l) { if (l!=null && l.isDirectory()) { File pom = new File(l, "pom.xml"); return pom.isFile(); } return false; } public final LiveExpression<GrailsVersion> projectGrailsVersion = new LiveExpression<GrailsVersion>(null) { protected GrailsVersion compute() { //It is slighly better to also check whether the project location is valid, otherwise we can't hope to //determine the version anyway. if (locationValidator.getValue().isOk()) { return GrailsVersion.getGrailsVersion(location.getValue()); } else { return GrailsVersion.UNKNOWN; } } } .dependsOn(location) .dependsOn(locationValidator); /** * 'maven' state is valid if either the selected project is not a maven project, or ignoreMavenWarning * has been selected. */ public final LiveExpression<ValidationResult> mavenValidator = new Validator() { @Override protected ValidationResult compute() { if (isMaven.getValue()) { if (!ignoreMavenWarning.getValue()) { return error("Mavenized project"); } } return ValidationResult.OK; } } .dependsOn(isMaven) .dependsOn(ignoreMavenWarning); /** * To be valid, a Grails install must be selected that matches the Grails version of the selected project. */ public final LiveExpression<ValidationResult> installValidator = new Validator() { protected ValidationResult compute() { IGrailsInstall install = grailsInstall.getValue(); if (install == null) { return error("No Grails install selected"); } else { GrailsVersion installVersion = install.getVersion(); GrailsVersion projectVersion = GrailsVersion.getGrailsVersion(location.getValue()); if (projectVersion.equals(GrailsVersion.UNKNOWN)) { return error("Unable to determine Grails version for the project"); } else if (!installVersion.equals(projectVersion)) { return error("Project Grails version ("+projectVersion+ ") does not match install version ("+installVersion+")"); } } return ValidationResult.OK; }; } .dependsOn(grailsInstall) .dependsOn(projectGrailsVersion); { /* * If a project is selected and a matching Grails install is not, then try to automatically select * a matching Grails install. */ projectGrailsVersion.addListener(new ValueListener<GrailsVersion>() { public void gotValue(LiveExpression<GrailsVersion> exp, GrailsVersion projectVersion) { if (projectVersion!=null) { IGrailsInstall instl = grailsInstall.getValue(); if (instl==null || !projectVersion.equals(instl.getVersion())) { instl = projectVersion.getInstall(); if (instl!=null) { grailsInstall.setValue(instl); } } } } }); } private boolean isDefaultProjectLocation(String projectName, File projectDir) { IPath workspaceLoc = Platform.getLocation(); if (workspaceLoc!=null) { File defaultLoc = new File(workspaceLoc.toFile(), projectName); return defaultLoc.equals(projectDir); } return false; } public boolean perform(IProgressMonitor mon) throws CoreException { int totalWork = 2; File copyLoc = getCopyLocation(); if (copyLoc!=null) { totalWork++; } mon.beginTask("Import", totalWork); try { //1: copy files to workspace if (copyLoc!=null) { FileUtils.copyDirectory(location.getValue(), copyLoc); mon.worked(1); } IWorkspace ws = ResourcesPlugin.getWorkspace(); File projectDir = copyLoc!=null?copyLoc:location.getValue(); String projectName = projectDir.getName(); //2: create project IProjectDescription projectDescription = ws.newProjectDescription(projectName); if (!isDefaultProjectLocation(projectName, projectDir)) { projectDescription.setLocation(new Path(projectDir.getAbsolutePath())); } IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); project.create(projectDescription, new SubProgressMonitor(mon, 1)); //3: configure project IGrailsInstall install = grailsInstall.getValue(); if (install!=null) { File projectAbsoluteFile = location.getValue(); if (projectAbsoluteFile!=null) { IPath projectAbsolutePath = new Path(projectAbsoluteFile.toString()); GrailsCommandUtils.eclipsifyProject(grailsInstall.getValue(), projectAbsolutePath); return true; } } mon.worked(1); return false; } catch (IOException e) { throw new CoreException(new Status(IStatus.ERROR, GrailsCoreActivator.PLUGIN_ID, "Import failed", e)); } finally { mon.done(); } } public String getProjectName() { File loc = location.getValue(); if (loc!=null) { return loc.getName(); } return null; } }