/*******************************************************************************
* Copyright 2014 Google Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.google.gcp.eclipse.testing;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.eclipse.core.resources.ICommand;
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.IWorkspaceDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Set;
/**
* Utilities for setting up {@link IProject}s in OSGi tests.
*/
public class ProjectTestUtil {
private ProjectTestUtil() {} // Non-instantiatable utility class
/** IDs for project natures */
public static final String JAVA_NATURE = "org.eclipse.jdt.core.javanature";
public static final String JAVA_BUILDER_ID = "org.eclipse.jdt.core.javabuilder";
public static final String SOURCE_FOLDER = "src";
/**
* Enables or disables automatic building of projects.
*/
public static void setAutoBuilding(boolean enable) throws CoreException {
IWorkspaceDescription desc = ResourcesPlugin.getWorkspace().getDescription();
if (desc.isAutoBuilding() != enable) {
desc.setAutoBuilding(enable);
ResourcesPlugin.getWorkspace().setDescription(desc);
}
}
/**
* Returns the {@link ICommand} for the specified builder, or {@code null} if the builder does not
* exist.
*/
public static ICommand getBuilder(IProject project, String builderId) throws CoreException {
IProjectDescription description = project.getDescription();
for (ICommand command : description.getBuildSpec()) {
if (command.getBuilderName().equals(builderId)) {
return command;
}
}
return null;
}
/**
* Adds the specified builder to an existing project.
*/
public static void addBuilder(IProject project, String builderId) throws CoreException {
Preconditions.checkArgument(project.exists());
IProjectDescription description = project.getDescription();
List<ICommand> commands = Lists.newArrayList(description.getBuildSpec());
for (ICommand command : commands) {
if (command.getBuilderName().equals(builderId)) {
return;
}
}
ICommand command = description.newCommand();
command.setBuilderName(builderId);
commands.add(command);
description.setBuildSpec(commands.toArray(new ICommand[commands.size()]));
project.setDescription(description, IResource.FORCE, null);
}
/**
* Adds the nature defined by {@code natureId} to {@code project}.
*/
public static void addNature(IProject project, String natureId) throws CoreException {
Preconditions.checkArgument(project.exists());
IProjectDescription description = project.getDescription();
Set<String> natures = Sets.newHashSet(description.getNatureIds());
natures.add(natureId);
description.setNatureIds(natures.toArray(new String[natures.size()]));
project.setDescription(description, null);
}
/**
* Returns the absolute path to the root of the CitC or Piper client.
*/
public static IPath getSourceLocation(IProject project) {
return project.getLocation().append(SOURCE_FOLDER);
}
/**
* Returns the working directory for the test.
*/
private static IPath getWorkingDirectory() {
return ResourcesPlugin.getWorkspace().getRoot().getLocation();
}
/**
* Creates a file relative to the project's "src" folder. Files created this way become visible
* after the next refresh operation.
*/
public static void createFile(IProject project, String relativePath) throws IOException {
IPath root = getSourceLocation(project);
IPath path = Path.fromOSString(relativePath);
Preconditions.checkArgument(!path.isAbsolute());
PathTestUtil.touch(root.append(path));
}
/**
* Creates a directory relative to the project's "src" folder. Directories created this way become
* visible after the next refresh operation.
*/
public static void createDirectory(IProject project, String relativePath) throws IOException {
IPath root = getSourceLocation(project);
IPath path = Path.fromOSString(relativePath);
Preconditions.checkArgument(!path.isAbsolute());
PathTestUtil.makeDir(root.append(path));
}
/**
* Clears out existing projects and the client files that back them.
*/
public static void cleanup() {
// Clear out existing projects
for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
// Close the project before deleting it to make sure all resource synchronization is done,
// otherwise we can see errors from Guide's resource filtering.
if (project.exists()) {
try {
project.close(null);
project.delete(true, true, null);
} catch (CoreException e) {
e.printStackTrace(); // Log the error but don't flag a test failure.
}
}
}
// Clear out any backing files.
File workingDirectory = getWorkingDirectory().toFile();
if (workingDirectory.exists()) {
for (File child : workingDirectory.listFiles()) {
if (!child.getName().equals(".metadata")) {
try {
PathTestUtil.deleteRecursively(Path.fromOSString(child.getAbsolutePath()));
} catch (IOException e) {
e.printStackTrace(); // Log the error but don't flag a test failure.
}
}
}
}
}
/**
* Creates and returns an instance of {@code NullProgressMonitor}.
*/
public static NullProgressMonitor npm() {
return new NullProgressMonitor();
}
/**
* Creates a simple project.
*
* @param projectName the name of the project
* @param natureIds an array of natures IDs to set on the project, or {@code null} if none should
* be set
* @return the created project
* @throws CoreException if the project is not created
*/
public static IProject createSimpleProject(String projectName, String... natureIds)
throws CoreException {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
if (project.exists()) {
project.delete(true, true, npm());
}
project.create(npm());
project.open(npm());
if (natureIds != null) {
IProjectDescription desc = project.getDescription();
desc.setNatureIds(natureIds);
project.setDescription(desc, npm());
}
return project;
}
/**
* Creates a Java project with the given name and the specified raw classpath.
*/
public static IJavaProject createProject(String projectName, IClasspathEntry[] rawClasspaths)
throws CoreException {
IProject project = createSimpleProject(projectName, JAVA_NATURE);
IJavaProject javaProject = JavaCore.create(project);
javaProject.setRawClasspath(rawClasspaths, npm());
return javaProject;
}
/**
* Creates a Java project with the given name and a "src" folder and the default JRE library on
* its classpath.
*/
public static IJavaProject createProject(String projectName) throws CoreException {
IClasspathEntry[] classpath = new IClasspathEntry[] {
JavaCore.newSourceEntry(Path.fromOSString("/" + projectName + "/" + SOURCE_FOLDER)),
JavaCore.newContainerEntry(Path.fromOSString("org.eclipse.jdt.launching.JRE_CONTAINER"))};
return ProjectTestUtil.createProject(projectName, classpath);
}
/**
* Creates a META-INF/persistence.xml file for JPA persistence
*/
public static void createPersistenceFile(IProject project) throws CoreException {
String[] persistenceFileData = new String[] {
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<persistence version=\"2.0\" xmlns=\"http://java.sun.com/xml/ns/persistence\" ",
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ",
" xsi:schemaLocation=\"http://java.sun.com/xml/ns/persistence ",
" http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd\">",
" <persistence-unit name=\"JPA1\">",
" </persistence-unit>",
"</persistence>"};
IFolder srcFolder = project.getFolder("src");
if (!srcFolder.exists()) {
srcFolder.create(true, true, null);
}
IFolder metaFolder = srcFolder.getFolder("META-INF");
if (!metaFolder.exists()) {
metaFolder.create(true, true, null);
}
IFile persistenceXml = metaFolder.getFile("persistence.xml");
if (!persistenceXml.exists()) {
String data = Joiner.on('\n').join(persistenceFileData);
InputStream is = new ByteArrayInputStream(Charset.forName("UTF-8").encode(data).array());
persistenceXml.create(is, true, null);
}
}
}