/**
* Copyright (c) 2015 Codetrails GmbH. 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
*
* Contributors: Simon Laffoy - initial API and implementation.
*/
package org.eclipse.recommenders.testing.rcp.completion.rules;
import static com.google.common.collect.Sets.newHashSet;
import static java.io.File.separator;
import static java.util.Arrays.asList;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import org.apache.commons.lang3.ArrayUtils;
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.IWorkspaceRunnable;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.recommenders.utils.Constants;
import org.eclipse.recommenders.utils.Nonnull;
import org.eclipse.recommenders.utils.Throws;
import org.eclipse.recommenders.utils.Zips;
import com.google.common.collect.Sets;
public class TemporaryProject {
static final String BIN_FOLDER_NAME = "bin";
static final String SRC_FOLDER_NAME = "src";
static final String JAR_FOLDER_NAME = "jar";
private final Set<TemporaryFile> temporaryFiles = Sets.newHashSet();
private final IWorkspace workspace;
private final String name;
private final IProject project;
private IJavaProject javaProject;
TemporaryProject(TemporaryWorkspace ws, String name) {
this.workspace = ws.getWorkspace();
this.name = name;
this.project = workspace.getRoot().getProject(name);
createProject();
}
private void createProject() {
final IWorkspaceRunnable populate = new IWorkspaceRunnable() {
@Override
public void run(final IProgressMonitor monitor) throws CoreException {
createAndOpenProject(project);
if (!hasJavaNature(project)) {
addJavaNature(project);
addToClasspath(JavaRuntime.getDefaultJREContainerEntry());
addSourcePackageFragmentRoot(project);
}
}
private void createAndOpenProject(IProject project) throws CoreException {
if (!project.exists()) {
project.create(null);
}
project.open(null);
}
private boolean hasJavaNature(final IProject project) throws CoreException {
final IProjectDescription description = project.getDescription();
final String[] natures = description.getNatureIds();
return ArrayUtils.contains(natures, JavaCore.NATURE_ID);
}
private void addJavaNature(final IProject project) throws CoreException {
final IProjectDescription description = project.getDescription();
final String[] natures = description.getNatureIds();
final String[] newNatures = ArrayUtils.add(natures, JavaCore.NATURE_ID);
description.setNatureIds(newNatures);
project.setDescription(description, null);
javaProject = JavaCore.create(project);
}
private void addSourcePackageFragmentRoot(IProject project) throws CoreException {
// create the source folder
IFolder sourceFolder = project.getFolder(SRC_FOLDER_NAME);
sourceFolder.create(false, true, null);
// replace the classpath's project root entry with the src folder
IPackageFragmentRoot src = javaProject.getPackageFragmentRoot(sourceFolder);
IClasspathEntry[] entries = javaProject.getRawClasspath();
for (int i = 0; i < entries.length; i++) {
if (entries[i].getPath().toString().equals(separator + name)) {
entries[i] = JavaCore.newSourceEntry(src.getPath());
break;
}
}
javaProject.setRawClasspath(entries, null);
}
};
try {
workspace.run(populate, null);
} catch (final Exception e) {
e.printStackTrace();
Throws.throwUnhandledException(e);
}
javaProject = JavaCore.create(project);
}
public TemporaryProject withDependencyOn(TemporaryProject dependency) throws JavaModelException {
addToClasspath(JavaCore.newProjectEntry(dependency.getProject().getFullPath()));
return this;
}
public TemporaryProject withDependencyOnClassesOf(TemporaryProject dependency) throws JavaModelException {
IFolder classFileFolder = dependency.getProjectClassFileDirectory();
addToClasspath(JavaCore.newLibraryEntry(classFileFolder.getFullPath(), null, null));
return this;
}
public TemporaryProject withDependencyOnJarOf(TemporaryProject dependency) throws IOException, JavaModelException {
addToClasspath(JavaCore.newLibraryEntry(dependency.createJar(), null, null));
return this;
}
public TemporaryFile createFile(CharSequence code) throws CoreException {
TemporaryFile tempFile = new TemporaryFile(this, code);
temporaryFiles.add(tempFile);
return tempFile;
}
private void addToClasspath(@Nonnull final IClasspathEntry classpathEntry) throws JavaModelException {
final Set<IClasspathEntry> entries = newHashSet();
entries.addAll(asList(javaProject.getRawClasspath()));
entries.add(classpathEntry);
IClasspathEntry[] classpaths = entries.toArray(new IClasspathEntry[entries.size()]);
javaProject.setRawClasspath(classpaths, null);
}
private IFolder getProjectClassFileDirectory() {
return project.getFolder(BIN_FOLDER_NAME);
}
private Path createJar() throws IOException {
String jarPath = getJarPath();
String pathToClassDirectory = this.getAbsolutePathString() + separator + BIN_FOLDER_NAME;
File classFileDirectory = new File(pathToClassDirectory);
Zips.zip(classFileDirectory, new File(jarPath));
return new Path(jarPath);
}
public String getJarPath() {
return this.getAbsolutePathString() + separator + this.getName() + Constants.DOT_JAR;
}
String getName() {
return name;
}
IProject getProject() {
return project;
}
public IJavaProject getJavaProject() {
return javaProject;
}
String getAbsolutePathString() {
return project.getLocation().toString();
}
String getWorkspaceRelativePathString() {
return project.getFullPath().toString();
}
void refreshAndBuildProject() throws CoreException {
project.refreshLocal(IResource.DEPTH_INFINITE, null);
project.build(IncrementalProjectBuilder.FULL_BUILD, null);
}
}