/*******************************************************************************
* Copyright (c) 2015 Pivotal, 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, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.buildship;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import org.eclipse.buildship.core.projectimport.ProjectImportConfiguration;
import org.eclipse.buildship.core.util.gradle.GradleDistributionWrapper;
import org.eclipse.buildship.core.util.gradle.GradleDistributionWrapper.DistributionType;
import org.eclipse.buildship.core.util.progress.AsyncHandler;
import org.eclipse.buildship.core.workspace.SynchronizeGradleProjectJob;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.springframework.ide.eclipse.boot.wizard.content.BuildType;
import org.springframework.ide.eclipse.boot.wizard.importing.ImportConfiguration;
import org.springframework.ide.eclipse.boot.wizard.importing.ImportStrategy;
import org.springframework.ide.eclipse.boot.wizard.importing.ImportStrategyFactory;
import org.springsource.ide.eclipse.commons.core.SpringCoreUtils;
import org.springsource.ide.eclipse.commons.core.util.NatureUtils;
import com.google.common.collect.ImmutableList;
/**
* Importer strategy implementation for importing CodeSets into the workspace and set them
* up to use Buildship Gradle Tooling.
*
* @author Kris De Volder
*/
public class BuildshipImportStrategy extends ImportStrategy {
//TODO: the way progress is reported with the sub-job / join is not very nice (a double progress popup appears)
// Perhaps this so post has the answer to doing it a better way:
// http://stackoverflow.com/questions/14530200/eclipse-jobs-api-how-to-track-progress-for-job-scheduled-by-another-job
public BuildshipImportStrategy(BuildType buildType, String name, String notInstalledMessage) {
super(buildType, name, notInstalledMessage);
}
public static class Factory implements ImportStrategyFactory {
@Override
public ImportStrategy create(BuildType buildType, String name, String notInstalledMessage) throws Exception {
Assert.isLegal(buildType==BuildType.GRADLE);
Class.forName("org.eclipse.buildship.core.projectimport.ProjectImportConfiguration");
return new BuildshipImportStrategy(buildType, name, notInstalledMessage);
}
}
private IProject getProject(File projectLoc) {
for (IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
if (p.isAccessible()) {
IPath l = getLocation(p);
if (l!=null) {
File f = l.toFile();
if (projectLoc.equals(f)) {
return p;
}
}
}
}
return null;
}
private IPath getLocation(IProject p) {
//In eclipse... nothing is ever simple. No, you can not just ask a project for its location...
URI uri = p.getRawLocationURI();
if (uri==null) {
//This means project description doesn't specify location, which means project is in the
// default location
IPath wsloc = ResourcesPlugin.getWorkspace().getRoot().getLocation();
return wsloc.append(p.getName());
} else if (uri.getScheme().equals("file")) {
return new Path(uri.getPath());
}
return null;
}
@Override
public IRunnableWithProgress createOperation(final ImportConfiguration conf) {
return new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor mon) throws InvocationTargetException, InterruptedException {
mon.beginTask("Import Gradle Buildship project", 10);
try {
File loc = new File(conf.getLocation());
conf.getCodeSet().createAt(loc);
ProjectImportConfiguration conf = new ProjectImportConfiguration();
conf.setProjectDir(loc);
conf.setGradleDistribution(createGradleDistribution());
conf.setApplyWorkingSets(false);
SynchronizeGradleProjectJob job = new SynchronizeGradleProjectJob(
conf.toFixedAttributes(), ImmutableList.<String>of(),
AsyncHandler.NO_OP);
job.schedule();
// This doesn't work in e44 (api not available until e45):
job.join(0, new SubProgressMonitor(mon, 9));
// The below works, but makes more assumptions on the internal workings of SynchronizeGradleProjectJob
// Namely: how it implements Job.belongsTo to make itself belong to program family equal to its class name.
//Job.getJobManager().join(SynchronizeGradleProjectJob.class.getName(), new SubProgressMonitor(mon, 9));
IProject p = getProject(loc);
if (p!=null) {
NatureUtils.ensure(p, new SubProgressMonitor(mon, 1), SpringCoreUtils.NATURE_ID);
}
} catch (InterruptedException|InvocationTargetException e) {
throw e;
} catch (Exception e) {
throw new InvocationTargetException(e);
}
finally {
mon.done();
}
}
};
}
private GradleDistributionWrapper createGradleDistribution() {
DistributionType distributionType = DistributionType.WRAPPER;
String distributionConfiguration = null;
return GradleDistributionWrapper.from(distributionType, distributionConfiguration);
}
}