blob: 4e2ef4f845a05d6fdd4202b1453c00e33a97d22e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Hannes Wellmann - Bug 577629 - Unify project creation/deletion in tests
*******************************************************************************/
package org.eclipse.pde.ui.tests.util;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.pde.core.project.IBundleProjectDescription;
import org.eclipse.pde.core.project.IBundleProjectService;
import org.eclipse.pde.core.target.NameVersionDescriptor;
import org.eclipse.pde.internal.ui.wizards.IProjectProvider;
import org.eclipse.pde.internal.ui.wizards.plugin.NewProjectCreationOperation;
import org.eclipse.pde.internal.ui.wizards.plugin.PluginFieldData;
import org.eclipse.pde.ui.IBundleContentWizard;
import org.eclipse.pde.ui.templates.AbstractNewPluginTemplateWizard;
import org.eclipse.pde.ui.templates.ITemplateSection;
import org.eclipse.pde.ui.tests.project.ProjectCreationTests;
import org.eclipse.pde.ui.tests.runtime.TestUtils;
import org.junit.rules.TestRule;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.Version;
/**
* Utility class for project related operations
*/
public class ProjectUtils {
/**
* Used to create projects
*/
static class TestProjectProvider implements IProjectProvider {
private String fProjectName;
TestProjectProvider(String projectName) {
fProjectName = projectName;
}
@Override
public IPath getLocationPath() {
return ResourcesPlugin.getWorkspace().getRoot().getLocation();
}
@Override
public IProject getProject() {
return ResourcesPlugin.getWorkspace().getRoot().getProject(fProjectName);
}
@Override
public String getProjectName() {
return fProjectName;
}
}
/**
* Fake wizard
*/
static class TestBundleWizard extends AbstractNewPluginTemplateWizard {
@Override
protected void addAdditionalPages() {
}
@Override
public ITemplateSection[] getTemplateSections() {
return new ITemplateSection[0];
}
}
/**
* Constant representing the name of the output directory for a project.
* Value is: <code>bin</code>
*/
public static final String BIN_FOLDER = "bin";
/**
* Constant representing the name of the source directory for a project.
* Value is: <code>src</code>
*/
public static final String SRC_FOLDER = "src";
/**
* Create a plugin project with the given name and execution environment.
*
* @param projectName
* @param env
* environment for build path or <code>null</code> if default
* system JRE
* @return a new plugin project
* @throws CoreException
*/
public static IJavaProject createPluginProject(String projectName, IExecutionEnvironment env) throws Exception {
PluginFieldData data = new PluginFieldData();
data.setName(projectName);
data.setId(projectName);
data.setLegacy(false);
data.setHasBundleStructure(true);
data.setSimple(false);
data.setProvider("IBM");
data.setLibraryName(".");
data.setVersion("1.0.0");
data.setTargetVersion("3.5");
data.setOutputFolderName(BIN_FOLDER);
data.setSourceFolderName(SRC_FOLDER);
if (env != null) {
data.setExecutionEnvironment(env.getId());
}
data.setDoGenerateClass(true);
data.setClassname(projectName + ".Activator");
data.setEnableAPITooling(false);
data.setRCPApplicationPlugin(false);
data.setUIPlugin(false);
IProjectProvider provider = new TestProjectProvider(projectName);
IBundleContentWizard wizard = new TestBundleWizard();
NewProjectCreationOperation operation = new NewProjectCreationOperation(data, provider, wizard);
operation.run(new NullProgressMonitor());
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
IJavaProject javaProject = JavaCore.create(project);
TestUtils.waitForJobs("ProjectUtils.createPluginProject " + projectName, 100, 10000);
return javaProject;
}
private static final Set<IProject> IMPORTED_PROJECTS = ConcurrentHashMap.newKeySet();
public static IProject importTestProject(String path) throws IOException, CoreException {
URL entry = FileLocator.toFileURL(FrameworkUtil.getBundle(ProjectUtils.class).getEntry(path));
if (entry == null) {
throw new IllegalArgumentException(path + " does not exist");
}
IPath projectFile = Path.fromPortableString(entry.getPath()).append(IProjectDescription.DESCRIPTION_FILE_NAME);
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IProjectDescription projectDescription = workspace.loadProjectDescription(projectFile);
IProject project = workspace.getRoot().getProject(projectDescription.getName());
project.create(projectDescription, null);
project.open(null);
IMPORTED_PROJECTS.add(project);
return project;
}
public static List<IProject> createWorkspacePluginProjects(Iterable<NameVersionDescriptor> workspacePlugins)
throws CoreException {
List<IProject> projects = new ArrayList<>();
for (NameVersionDescriptor plugin : workspacePlugins) {
projects.add(createPluginProject(plugin.getId(), plugin.getVersion()));
}
return projects;
}
public static IProject createPluginProject(String bundleSymbolicName, String bundleVersion) throws CoreException {
return createPluginProject(bundleSymbolicName + bundleVersion.replace('.', '_'), bundleSymbolicName,
bundleVersion);
}
public static IProject createPluginProject(String projectName, String bundleSymbolicName, String version)
throws CoreException {
return createPluginProject(projectName, bundleSymbolicName, version, (d, s) -> {
});
}
public static IProject createPluginProject(String projectName, String bundleSymbolicName, String version,
BiConsumer<IBundleProjectDescription, IBundleProjectService> setup) throws CoreException {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
IBundleProjectService bundleProjectService = ProjectCreationTests.getBundleProjectService();
IBundleProjectDescription description = bundleProjectService.getDescription(project);
description.setSymbolicName(bundleSymbolicName);
if (version != null) {
description.setBundleVersion(Version.parseVersion(version));
}
setup.accept(description, bundleProjectService);
description.apply(null);
return project;
}
/**
* An (intended) {@link org.junit.ClassRule} that deletes all projects from
* the test-workspace before and after all tests are executed.
* <p>
* The intention is to ensure that the workspace is empty before the first
* method (static or not) of a test-class is called as well it is cleared
* after the last method has returned.
* </p>
* <p>
* For projects that are imported via {@link #importTestProject(String)} the
* content is not deleted, for other projects the content is deleted. This
* assumes that imported projects are resources in this Test-plugin while
* other projects are virtual and can safely be deleted.
* </p>
*/
public static final TestRule DELETE_ALL_WORKSPACE_PROJECTS_BEFORE_AND_AFTER = TestUtils.getThrowingTestRule( //
() -> { // Clean-up garbage of other test-classes
ProjectUtils.deleteWorkspaceProjects(Set.of());
return null;
}, o -> deleteWorkspaceProjects(Set.of()));
/**
* An (intended) {@link org.junit.Rule} that deletes the projects from the
* test-workspace , that where created during the test-case execution, after
* each test-case.
* <p>
* The intention is to delete those projects from the workspace that were
* created during the execution of a test-case, but to retain those that
* existed before (e.g. were created in a static initializer).
* </p>
* <p>
* For projects that are imported via {@link #importTestProject(String)} the
* content is not deleted, for other projects the content is deleted. This
* assumes that imported projects are resources in this Test-plugin while
* other projects are virtual and can safely be deleted.
* </p>
*/
public static final TestRule DELETE_CREATED_WORKSPACE_PROJECTS_AFTER = TestUtils.getThrowingTestRule( //
() -> Set.of(ResourcesPlugin.getWorkspace().getRoot().getProjects()), //
projectsBefore -> deleteWorkspaceProjects(projectsBefore));
private static void deleteWorkspaceProjects(Set<IProject> retainedProjects) throws CoreException {
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (IProject project : projects) {
if (!retainedProjects.contains(project)) {
boolean isImportedProject = IMPORTED_PROJECTS.remove(project);
// Don't delete content of imported projects because they are
// resources of this test plug-in and must not be deleted
project.delete(!isImportedProject, true, null);
}
}
// back-up, should not change anything if everything is properly used
IMPORTED_PROJECTS.retainAll(retainedProjects);
}
}