/*******************************************************************************
* Copyright (c) 2009-2012 CWI
* 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:
* * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
* * Emilie Balland - (CWI)
* * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI
*******************************************************************************/
package org.rascalmpl.eclipse.wizards;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.pde.core.project.IBundleProjectDescription;
import org.eclipse.pde.core.project.IBundleProjectService;
import org.eclipse.pde.core.project.IRequiredBundleDescription;
import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
import org.rascalmpl.eclipse.Activator;
import org.rascalmpl.eclipse.IRascalResources;
import org.rascalmpl.eclipse.repl.RascalTerminalRegistry;
import org.rascalmpl.eclipse.util.RascalEclipseManifest;
public class RascalProjectWizard extends BasicNewProjectResourceWizard {
@Override
public boolean performFinish() {
if (!super.performFinish()) {
return false;
}
final IProject project = getNewProject();
// this code initializes the project to be a PDE plugin project as well as a java project and
// puts the right classpath entries and plugin dependencies such that building and running will work.
IRunnableWithProgress job = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
try {
BundleContext context = Activator.getInstance().getBundle().getBundleContext();
ServiceReference<IBundleProjectService> ref = context.getServiceReference(IBundleProjectService.class);
try {
IBundleProjectService service = context.getService(ref);
IBundleProjectDescription plugin = service.getDescription(project);
//plugin.setBundleName(project.getName());
plugin.setBundleName(project.getName().replaceAll("[^a-zA-Z0-9_]", "_"));
project.setDefaultCharset("UTF-8", monitor); // now let's just force new rascal projects to be UTF-8.
initializeProjectAsRascalProject(project, monitor, service, plugin);
initializeProjectAsJavaProject(project);
RascalTerminalRegistry.launchTerminal(project.getName(), ILaunchManager.DEBUG_MODE);
}
finally {
context.ungetService(ref);
}
} catch (CoreException e) {
Activator.getInstance().logException("could not initialize Rascal project", e);
throw new InterruptedException();
}
}
private void initializeProjectAsRascalProject(
final IProject project, IProgressMonitor monitor,
IBundleProjectService service,
IBundleProjectDescription plugin) throws CoreException {
plugin.setSymbolicName(project.getName().replaceAll("[^a-zA-Z0-9_]", "_"));
plugin.setNatureIds(new String[] { IRascalResources.ID_RASCAL_NATURE, JavaCore.NATURE_ID, IBundleProjectDescription.PLUGIN_NATURE, IRascalResources.ID_TERM_NATURE});
plugin.setRequiredBundles(new IRequiredBundleDescription[] {
service.newRequiredBundle("rascal_eclipse", null, false, false)
});
plugin.setBundleVersion(Version.parseVersion("1.0.0"));
plugin.setExecutionEnvironments(new String[] { "JavaSE-1.8"}); // TODO: Is this a constant defined somewhere?
IProjectDescription description = project.getDescription();
description.setBuildConfigs(new String[] { "org.eclipse.jdt.core.javabuilder", "org.eclipse.pde.ManifestBuilder", "org.eclipse.pde.SchemaBuilder" });
project.setDescription(description, monitor);
new RascalEclipseManifest().createIfNotPresent(project);
plugin.apply(monitor);
}
/**
* This is a asynchronous job just because it triggers a Java rebuild (or something) that is really
* expensive.
*/
private void initializeProjectAsJavaProject(final IProject project) {
new Job("Initializing Java/Rascal Project " + project.getName()) {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
IJavaProject jProject = JavaCore.create(project);
IClasspathEntry[] oldClasspath = jProject.getRawClasspath();
IClasspathEntry[] newClasspath = new IClasspathEntry[oldClasspath.length + 2];
System.arraycopy(oldClasspath, 0, newClasspath, 2, oldClasspath.length);
newClasspath[0] = JavaRuntime.getDefaultJREContainerEntry();
newClasspath[1] = JavaCore.newContainerEntry(new Path("org.eclipse.pde.core.requiredPlugins"));
newClasspath[2] = JavaCore.newSourceEntry(project.getFolder("src").getFullPath().makeAbsolute());
jProject.setRawClasspath(newClasspath, monitor);
IFile cpFile = project.getFile(".classpath");
if (cpFile.exists())
cpFile.setHidden(true);
IFile pFile = project.getFile(".project");
if (pFile.exists())
pFile.setHidden(true);
IFile bpFile = project.getFile("build.properties");
if (bpFile.exists())
bpFile.setHidden(true);
jProject.getProject().refreshLocal(IResource.DEPTH_INFINITE, monitor);
return Status.OK_STATUS;
} catch (JavaModelException e) {
Activator.getInstance().logException("failed to initialize Rascal project with Java nature: " + project.getName(), e);
return Status.OK_STATUS;
} catch (CoreException e) {
Activator.getInstance().logException("failed to initialize Rascal project with Java nature: " + project.getName(), e);
return Status.OK_STATUS;
}
}
}.schedule();
}
};
if (project != null) {
try {
getContainer().run(true, true, job);
} catch (InvocationTargetException e) {
Activator.getInstance().logException("could not initialize new Rascal project", e);
return false;
} catch (InterruptedException e) {
return false;
}
return true;
}
return false;
}
}