| /** |
| * 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); |
| } |
| |
| } |