package org.erlide.ui.wizards; import java.io.ByteArrayInputStream; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.Collection; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResourceStatus; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.osgi.util.NLS; import org.eclipse.ui.ide.undo.CreateFileOperation; import org.eclipse.ui.ide.undo.CreateFolderOperation; import org.eclipse.ui.ide.undo.CreateProjectOperation; import org.eclipse.ui.statushandlers.IStatusAdapterConstants; import org.eclipse.ui.statushandlers.StatusAdapter; import org.eclipse.ui.statushandlers.StatusManager; import org.erlide.core.ErlangCore; import org.erlide.core.internal.builder.ErlangNature; import org.erlide.engine.ErlangEngine; import org.erlide.engine.NewProjectData; import org.erlide.engine.model.builder.BuilderProperties; import org.erlide.engine.model.builder.BuilderTool; import org.erlide.engine.model.root.IErlProject; import org.erlide.engine.model.root.ProjectConfigType; import org.erlide.ui.internal.ErlideUIPlugin; import org.erlide.ui.util.StatusUtil; import com.google.common.base.Charsets; import com.google.common.collect.Lists; public class ProjectCreator { private final String name; private final URI location; private final IProject[] referencedProjects; private final NewProjectData info; private final IAdaptable notifier; private final IRunnableContext context; public ProjectCreator(final String name, final URI location, final IProject[] referencedProjects, final NewProjectData info, final IRunnableContext context, final IAdaptable notifier) { this.name = name; this.location = location; this.referencedProjects = referencedProjects; this.info = info; this.notifier = notifier; this.context = context; } public IProject createProject() throws CoreException { final IWorkspace workspace = ResourcesPlugin.getWorkspace(); final IProject newProjectHandle = workspace.getRoot().getProject(name); if (newProjectHandle.exists()) { throw new CoreException(Status.OK_STATUS); } final IProjectDescription description = workspace.newProjectDescription(name); description.setLocationURI(location); // // update the referenced project if provided if (referencedProjects != null) { description.setReferencedProjects(referencedProjects); } // create the new project operation final IRunnableWithProgress op = new IRunnableWithProgress() { @Override public void run(final IProgressMonitor monitor) throws InvocationTargetException { final CreateProjectOperation op1 = new CreateProjectOperation(description, WizardMessages.NewProject_windowTitle); try { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=219901 // Making this undoable would be a bad idea op1.execute(monitor, notifier); newProjectHandle.open(monitor); description.setNatureIds(new String[] { ErlangCore.NATURE_ID }); newProjectHandle.setDescription(description, null); final BuilderTool builder = info.getBuilder(); ErlangNature.setErlangProjectBuilder(newProjectHandle, builder); createBuilderConfig(builder); createFolders(newProjectHandle, Lists.newArrayList(info.getOutputDir()), monitor); createFolders(newProjectHandle, info.getSourceDirs(), monitor); createFolders(newProjectHandle, info.getIncludeDirs(), monitor); createConfig(newProjectHandle, info.getConfigType(), monitor); final IErlProject erlProject = ErlangEngine.getInstance().getModel() .getErlangProject(newProjectHandle); erlProject.setConfigType(info.getConfigType()); final BuilderProperties builderProperties = new BuilderProperties(); builderProperties.setBuilderTool(builder); builderProperties .setCompileTarget(info.getBuilderData().get("compile")); builderProperties.setCleanTarget(info.getBuilderData().get("clean")); erlProject.setBuilderProperties(builderProperties); erlProject.setProperties(info); } catch (final Exception e) { throw new InvocationTargetException(e); } } }; // run the new project creation operation try { context.run(false, true, op); } catch (final InterruptedException e) { return null; } catch (final InvocationTargetException e) { final Throwable t = e.getTargetException(); if (t instanceof ExecutionException && t.getCause() instanceof CoreException) { final CoreException cause = (CoreException) t.getCause(); StatusAdapter status; if (cause.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) { status = new StatusAdapter( StatusUtil.newStatus(IStatus.WARNING, NLS.bind( WizardMessages.NewProject_caseVariantExistsError, newProjectHandle.getName()), cause)); } else { status = new StatusAdapter( StatusUtil.newStatus(cause.getStatus().getSeverity(), WizardMessages.NewProject_errorMessage, cause)); } status.setProperty(IStatusAdapterConstants.TITLE_PROPERTY, WizardMessages.NewProject_errorMessage); StatusManager.getManager().handle(status, StatusManager.BLOCK); } else { final StatusAdapter status = new StatusAdapter(new Status(IStatus.WARNING, ErlideUIPlugin.PLUGIN_ID, 0, NLS.bind(WizardMessages.NewProject_internalError, t.getMessage()), t)); status.setProperty(IStatusAdapterConstants.TITLE_PROPERTY, WizardMessages.NewProject_errorMessage); StatusManager.getManager().handle(status, StatusManager.LOG | StatusManager.BLOCK); } return null; } return newProjectHandle; } private void createConfig(final IProject newProjectHandle, final ProjectConfigType configType, final IProgressMonitor monitor) throws ExecutionException { System.out.println("create config?? " + configType); switch (configType) { case REBAR: case EMAKE: final IFile cfg = newProjectHandle.getFile(configType.getConfigName()); final String contents = getConfigContent(info, configType); final CreateFileOperation fop = new CreateFileOperation(cfg, null, // TODO real encoding? new ByteArrayInputStream(contents.getBytes(Charsets.ISO_8859_1)), "creating file " + cfg.getName()); fop.execute(monitor, notifier); break; case INTERNAL: break; default: break; } } private String getConfigContent(final NewProjectData info2, final ProjectConfigType configType) { // TODO get config content System.out.println("TO DO: get config content " + info2 + " " + configType); switch (configType) { case EMAKE: return ""; case REBAR: return ""; default: return ""; } } private void createBuilderConfig(final BuilderTool builderTool) { // TODO create builder config System.out.println("TODO: create builder config " + builderTool); } private void createFolders(final IProject project, final Collection<IPath> pathList, final IProgressMonitor monitor) throws CoreException, ExecutionException { if (pathList == null) { return; } for (final IPath path : pathList) { // only create in-project paths if (!path.isAbsolute() && !path.toString().equals(".") && !path.isEmpty()) { final IFolder folder = project.getFolder(path); createFolderHelper(folder, monitor); } } } /** * recursively create a folder path. */ private void createFolderHelper(final IFolder folder, final IProgressMonitor monitor) throws CoreException, ExecutionException { if (!folder.exists()) { final IContainer parent = folder.getParent(); if (parent instanceof IFolder && !((IFolder) parent).exists()) { createFolderHelper((IFolder) parent, monitor); } final CreateFolderOperation fop = new CreateFolderOperation(folder, null, "creating folder " + folder.getName()); fop.execute(monitor, notifier); } } }