/** * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package org.python.pydev.plugin; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; 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.OperationCanceledException; import org.eclipse.core.runtime.SubProgressMonitor; import org.python.pydev.core.IPythonNature; import org.python.pydev.plugin.nature.PythonNature; import com.aptana.shared_core.callbacks.ICallback; public class PyStructureConfigHelpers { /** * Creates a project resource handle for the current project name field value. * <p> * This method does not create the project resource; this is the responsibility * of <code>IProject::create</code> invoked by the new project resource wizard. * </p> * * @return the new project resource handle */ public static IProject getProjectHandle(String projectName) { return ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); } /** * @see #createPydevProject(IProjectDescription, IProject, IProgressMonitor, String, String, ICallback, ICallback, ICallback) */ public static void createPydevProject(IProjectDescription description, IProject projectHandle, IProgressMonitor monitor, String projectType, String projectInterpreter, ICallback<List<IContainer>, IProject> getSourceFolderHandlesCallback, ICallback<List<String>, IProject> getExternalSourceFolderHandlesCallback) throws OperationCanceledException, CoreException { createPydevProject(description, projectHandle, monitor, projectType, projectInterpreter, getSourceFolderHandlesCallback, getExternalSourceFolderHandlesCallback, null); } /** * Creates a project resource given the project handle and description. * * @param description the project description to create a project resource for * * @param projectHandle the project handle to create a project resource for * * @param monitor the progress monitor to show visual progress with * * @param projectType one of the PYTHON_VERSION_XXX or JYTHON_VERSION_XXX constants from {@link IPythonNature} * * @param projectInterpreter This is the interpreter to be added. It's one of the interpreters available from * IInterpreterManager.getInterpreters. * * * @param getSourceFolderHandlesCallback This is a callback that's called with the project and it should * return a list of handles with the folders that should be created and added to the project as source folders. * (if null, no source folders should be created) * * E.g.: To create a 'src' source folder, the callback should be: * * ICallback<List<IContainer>, IProject> getSourceFolderHandlesCallback = new ICallback<List<IContainer>, IProject>(){ * * public List<IContainer> call(IProject projectHandle) { * IContainer folder = projectHandle.getFolder("src"); * List<IContainer> ret = new ArrayList<IContainer>(); * ret.add(folder); * return ret; * } * }; * * * @param getExternalSourceFolderHandlesCallback Same as the getSourceFolderHandlesCallback, but returns a list of * Strings to the actual paths in the filesystem that should be added as external source folders. * (if null, no external source folders should be created) * * @param getVariableSubstitutionCallback Same as getSourceFolderHandlesCallback, but returns a map of String, String, * so that the keys in the map can be used to resolve the source folders paths (project and external). * * @exception CoreException if the operation fails * @exception OperationCanceledException if the operation is canceled */ public static void createPydevProject(IProjectDescription description, IProject projectHandle, IProgressMonitor monitor, String projectType, String projectInterpreter, ICallback<List<IContainer>, IProject> getSourceFolderHandlesCallback, ICallback<List<String>, IProject> getExternalSourceFolderHandlesCallback, ICallback<Map<String, String>, IProject> getVariableSubstitutionCallback) throws CoreException, OperationCanceledException { try { monitor.beginTask("", 2000); //$NON-NLS-1$ projectHandle.create(description, new SubProgressMonitor(monitor, 1000)); if (monitor.isCanceled()) { throw new OperationCanceledException(); } projectHandle.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 1000)); String projectPythonpath = null; //also, after creating the project, create a default source folder and add it to the pythonpath. if (getSourceFolderHandlesCallback != null) { List<IContainer> sourceFolders = getSourceFolderHandlesCallback.call(projectHandle); if (sourceFolders != null && sourceFolders.size() > 0) { StringBuffer buf = new StringBuffer(); for (IContainer container : sourceFolders) { if (container instanceof IFolder) { IFolder iFolder = (IFolder) container; iFolder.create(true, true, monitor); } else if (container instanceof IProject) { //continue (must be the passed project which was already created) } else { throw new RuntimeException("Expected container to be an IFolder or IProject. Was: " + container); } if (buf.length() > 0) { buf.append("|"); } buf.append(container.getFullPath().toString()); } projectPythonpath = buf.toString(); } } String externalProjectPythonpath = null; if (getExternalSourceFolderHandlesCallback != null) { List<String> externalPaths = getExternalSourceFolderHandlesCallback.call(projectHandle); if (externalPaths != null && externalPaths.size() > 0) { StringBuffer buf = new StringBuffer(); for (String path : externalPaths) { if (buf.length() > 0) { buf.append("|"); } buf.append(path); } externalProjectPythonpath = buf.toString(); } } Map<String, String> variableSubstitution = null; if (getVariableSubstitutionCallback != null) { variableSubstitution = getVariableSubstitutionCallback.call(projectHandle); } //we should rebuild the path even if there's no source-folder (this way we will re-create the astmanager) PythonNature.addNature(projectHandle, null, projectType, projectPythonpath, externalProjectPythonpath, projectInterpreter, variableSubstitution); } finally { monitor.done(); } } /** * Creates a new project resource with the entered name. * * @param projectName The name of the project * @param projectLocationPath the location for the project. If null, the default location (in the workspace) * will be used to create the project. * @param references The projects that should be referenced from the newly created project * * @return the created project resource, or <code>null</code> if the project was not created * @throws CoreException * @throws OperationCanceledException */ public static IProject createPydevProject(String projectName, IPath projectLocationPath, IProject[] references, IProgressMonitor monitor, String projectType, String projectInterpreter, ICallback<List<IContainer>, IProject> getSourceFolderHandlesCallback, ICallback<List<String>, IProject> getExternalSourceFolderHandlesCallback, ICallback<Map<String, String>, IProject> getVariableSubstitutionCallback) throws OperationCanceledException, CoreException { // get a project handle final IProject projectHandle = getProjectHandle(projectName); IWorkspace workspace = ResourcesPlugin.getWorkspace(); final IProjectDescription description = workspace.newProjectDescription(projectHandle.getName()); description.setLocation(projectLocationPath); // update the referenced project if provided if (references != null && references.length > 0) { description.setReferencedProjects(references); } createPydevProject(description, projectHandle, monitor, projectType, projectInterpreter, getSourceFolderHandlesCallback, getExternalSourceFolderHandlesCallback, getVariableSubstitutionCallback); return projectHandle; } }