blob: f5a65f88f61c1d2b903636896911a46648281938 [file] [log] [blame]
/**
* Copyright (c) 2009-2010 Thales Corporate Services S.A.S.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Thales Corporate Services S.A.S - initial API and implementation
*/
package org.eclipse.egf.common.helper;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
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.IResource;
import org.eclipse.core.resources.IResourceRuleFactory;
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.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.egf.common.EGFCommonPlugin;
import org.eclipse.egf.common.constant.EGFCommonConstants;
import org.eclipse.egf.common.generator.IEgfGeneratorConstants;
import org.eclipse.emf.codegen.ecore.Generator;
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.osgi.util.NLS;
import org.eclipse.pde.core.plugin.IPluginModelBase;
/**
* Workspace projects helper.
*
* @author brocard
*/
public class ProjectHelper {
private ProjectHelper() {
// Prevent Instantiation
}
/**
* Obtains a scheduling rule to schedule myself on to give my delegate
* access to the specified affected resources.
*
* @param projects
* @return the appropriate scheduling rule, or <code>null</code> if
* none is required
*/
public static ISchedulingRule getRule(List<IProject> projects) {
ISchedulingRule result = null;
if (projects.isEmpty() == false) {
IResourceRuleFactory factory = ResourcesPlugin.getWorkspace().getRuleFactory();
for (IResource next : projects) {
result = MultiRule.combine(result, factory.modifyRule(next));
}
}
return result;
}
/**
* Returns the workspace root default charset encoding.
*
* @return the name of the default charset encoding for workspace root.
* @see IContainer#getDefaultCharset()
* @see ResourcesPlugin#getEncoding()
* @since 3.0
*/
public static String getEncoding(IProject project) {
// project default encoding first
if (project != null) {
try {
return project.getDefaultCharset();
} catch (Throwable t) {
// fails silently
}
}
// default platform fallback
try {
return ResourcesPlugin.getWorkspace().getRoot().getDefaultCharset();
} catch (IllegalStateException ise) {
// happen when there's no workspace (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=216817)
// or when it is shutting down (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=60687)
return System.getProperty("file.encoding"); //$NON-NLS-1$
} catch (CoreException ce) {
// fails silently and return plugin global encoding if core exception occurs
}
return ResourcesPlugin.getEncoding();
}
/**
* Required plug-ins class path entry path identifier.
*/
protected static final String CLASS_PATH_ENTRY_REQUIRED_PLUGINS_PATH_ID = "requiredPlugins"; //$NON-NLS-1$
/**
* Project existence status after check.<br>
* The project already exists (including default structure), or it has just
* been created, or creation process failed.<br>
* Internal purpose only.
*/
public enum ProjectExistenceStatus {
ALREADY_EXISTS, CREATED, CREATION_FAILED
}
/**
* Get project from its name.<br>
* It is assumed that this project name refers to a plug-in.<br>
* If not, the method
* <code>ResourcesPlugin.getWorkspace().getRoot().getProject(projectName_p)</code>
* is invoked as result.
*
* @param bundleId
* A project name that points to a plug-in in the workspace.
* @return IProject
*/
public static IProject getProject(String bundleId) {
// Precondition.
if (bundleId == null) {
return null;
}
return ResourcesPlugin.getWorkspace().getRoot().getProject(bundleId);
}
/**
* Get the IProject from an IPath
*
* @param path
* @return null if not applicable
*/
public static IProject getProject(IPath path) {
// Precondition.
if (path == null) {
return null;
}
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
if (file == null) {
return null;
}
return file.getProject();
}
/**
* Get the IProject for specified plug-in model.
*
* @param model
* @return null if the plug-in is not in the workspace.
*/
public static IProject getProject(IPluginModelBase model) {
// Precondition.
if (model == null) {
return null;
}
IResource underlyingResource = model.getUnderlyingResource();
if (underlyingResource != null) {
return underlyingResource.getProject();
}
return null;
}
/**
* Refresh given project in the workspace.
*
* @param project
* @param monitor
*/
public static void refreshProject(IProject project, IProgressMonitor monitor) throws CoreException {
refreshProject(project, IResource.DEPTH_INFINITE, monitor);
}
/**
* Refresh a project in the workspace.
*
* @param project
* @param depth
* @param monitor
*/
public static void refreshProject(IProject project, int depth, IProgressMonitor monitor) throws CoreException {
project.refreshLocal(depth, monitor);
}
/**
* Create a source folder in given project.
*
* @param folder
* the name of the source folder.
* @param project
* the hosting project.
* @param monitor
* progress monitor.
*/
public static void createSourceFolder(String folder, IProject project, IProgressMonitor monitor) throws CoreException {
// Preconditions
if (folder == null || project == null || monitor == null) {
return;
}
try {
// Get the related java project.
IJavaProject javaProject = JavaCore.create(project);
// Get all source entries.
IClasspathEntry[] sourceEntries = javaProject.getRawClasspath();
// Add a generated source folder.
IPath generatedSourceFolderPath = project.getFullPath().append(folder);
createFolder(folder, project, new SubProgressMonitor(monitor, 1));
// Create a new source entry for the 'generated' source folder.
IClasspathEntry generatedSourceEntry = JavaCore.newSourceEntry(generatedSourceFolderPath);
IClasspathEntry[] newEntries = new IClasspathEntry[sourceEntries.length + 1];
// Copy the 'src' source entry.
newEntries[0] = sourceEntries[0];
// Add the 'generated' entry.
newEntries[1] = generatedSourceEntry;
// Copy the remaining entries.
System.arraycopy(sourceEntries, 1, newEntries, 2, sourceEntries.length - 1);
// Set the new entries on the java project.
javaProject.setRawClasspath(newEntries, new SubProgressMonitor(monitor, 1));
} catch (Throwable t) {
throw new CoreException(EGFCommonPlugin.getDefault().newStatus(IStatus.ERROR, NLS.bind("ProjectHelper.createSourceFolder(..) _ project ''{0}'' folder ''{1}''.", project.getName(), folder), t)); //$NON-NLS-1$
}
return;
}
/**
* Create a folder with given name in given project.
*
* @param folderName
* @param project
* @param monitor
* @return <code>null</code> if creation failed.
*/
public static IFolder createFolder(String folderName, IProject project, IProgressMonitor monitor) throws CoreException {
IFolder folder = project.getFolder(folderName);
// Create the physical resource.
if (folder.exists() == false) {
// Get parent path.
IPath parentPath = new Path(folderName);
if (parentPath.segmentCount() > 1) {
parentPath = parentPath.removeLastSegments(1);
// Make sure parent exists first.
createFolder(parentPath.toString(), project, monitor);
}
// Then try and create given folder.
try {
folder.create(true, true, monitor);
} catch (Throwable t) {
throw new CoreException(EGFCommonPlugin.getDefault().newStatus(IStatus.ERROR, NLS.bind("ProjectHelper.createFolder(..) _ project ''{0}'' folder ''{1}''.", project.getName(), folderName), t)); //$NON-NLS-1$
}
}
return folder;
}
/**
* Make sure named project exists.<br>
* If not try and create a new one with given name.
*
* @param projectName
* The expected project name.
* @param cleanProject
* true to clean project structure after creation, false otherwise.
* @param projectType
* {@link Generator#EMF_EMPTY_PROJECT_STYLE} see other values.
* @return {@link ProjectExistenceStatus} value.
*/
private static ProjectExistenceStatus ensureProjectExists(String projectName, boolean cleanProject, int projectType, IProgressMonitor monitor) throws CoreException {
ProjectExistenceStatus result = ProjectExistenceStatus.CREATION_FAILED;
// Precondition.
if (projectName == null) {
return result;
}
IFile file = FileHelper.getFile(projectName + IEgfGeneratorConstants.PROJECT_ROOT_FILE);
// Project already exists, stop here.
if (file != null && file.exists()) {
return ProjectExistenceStatus.ALREADY_EXISTS;
}
// Else, try and create an EMF project.
IPath projectLocationPath = new Path(EGFCommonConstants.SLASH_CHARACTER + projectName);
IProject resultingProject = Generator.createEMFProject(projectLocationPath.append(EGFCommonConstants.SLASH_CHARACTER + IEgfGeneratorConstants.SRC_FOLDER), null, Collections.<IProject> emptyList(), monitor, projectType, Collections.EMPTY_LIST);
if (resultingProject != null && resultingProject.exists()) {
result = ProjectExistenceStatus.CREATED;
// If project should be cleaned, do it.
if (cleanProject) {
cleanProjectStructure(resultingProject, monitor);
}
} else {
result = ProjectExistenceStatus.CREATION_FAILED;
}
return result;
}
/**
* Clean newly created project structure.<br/>
* Remove plug-in dependencies class path container from given project (if
* applicable).<br/>
* Also set nature back to Java one.
*
* @param project
*/
private static void cleanProjectStructure(IProject project, IProgressMonitor monitor) throws CoreException {
IJavaProject javaProject = JavaCore.create(project);
// Precondition.
if (javaProject == null) {
return;
}
// Restore Java nature only.
String natureIds[] = new String[] {
JavaCore.NATURE_ID
};
IProjectDescription description = project.getDescription();
description.setNatureIds(natureIds);
project.setDescription(description, monitor);
// Get raw class path.
IClasspathEntry[] rawClasspath = null;
try {
rawClasspath = javaProject.getRawClasspath();
} catch (JavaModelException jme) {
throw new CoreException(EGFCommonPlugin.getDefault().newStatus(IStatus.ERROR, NLS.bind("ProjectHelper.cleanProjectStructure(..) _ project ''{0}''.", project.getName()), jme)); //$NON-NLS-1$
}
// Iterate over class path elements.
if (rawClasspath != null && rawClasspath.length != 0) {
List<IClasspathEntry> newRawClasspath = new ArrayList<IClasspathEntry>(rawClasspath.length);
for (IClasspathEntry classpathEntry : rawClasspath) {
if (classpathEntry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
// Do not retain required plug-ins container.
IPath path = classpathEntry.getPath();
if (CLASS_PATH_ENTRY_REQUIRED_PLUGINS_PATH_ID.equals(path.getFileExtension()) == false) {
newRawClasspath.add(classpathEntry);
}
} else {
newRawClasspath.add(classpathEntry);
}
}
// Set new raw class path.
try {
javaProject.setRawClasspath(newRawClasspath.toArray(new IClasspathEntry[newRawClasspath.size()]), new NullProgressMonitor());
} catch (JavaModelException jme) {
throw new CoreException(EGFCommonPlugin.getDefault().newStatus(IStatus.ERROR, NLS.bind("ProjectHelper.cleanProjectStructure(..) _ project ''{0}''.", project.getName()), jme)); //$NON-NLS-1$
}
}
}
/**
* Make sure named plug-in project exists.<br>
* If not try and create a new one with given name.
*
* @param projectName
* The expected project name.
* @return ProjectExistenceStatus
*/
public static ProjectExistenceStatus ensurePluginProjectExists(String projectName, IProgressMonitor monitor) throws CoreException {
return ensureProjectExists(projectName, false, Generator.EMF_PLUGIN_PROJECT_STYLE, monitor);
}
/**
* Make sure named project exists.<br>
* If not try and create a new one with given name.
*
* @param projectName
* The expected project name.
* @return ProjectExistenceStatus
*/
public static ProjectExistenceStatus ensureProjectExists(String projectName, IProgressMonitor monitor) throws CoreException {
return ensureProjectExists(projectName, true, Generator.EMF_EMPTY_PROJECT_STYLE, monitor);
}
}