/**
* Copyright 2006-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.mybatis.generator.eclipse.core.tests.callback;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
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.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
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.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
/**
* A lot of this code was originally copied from org.eclipse.jdt.core.tests.util and
* other classes in the eclipse test projects.
*
* Method in this class should only be used by the ShellCallbackTests because they
* require a project in the workspace.
*
*/
public class WorkspaceUtilities {
private static int DELETE_MAX_WAIT = 10000;
private static int DELETE_MAX_TIME = 0;
private static IProject getProject(String project) {
return getWorkspaceRoot().getProject(project);
}
private static IProject createProject(String projectName) throws CoreException {
final IProject project = getWorkspaceRoot().getProject(projectName);
IWorkspaceRunnable create = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
project.create(null);
project.open(null);
}
};
getWorkspace().run(create, null);
return project;
}
static IWorkspace getWorkspace() {
return ResourcesPlugin.getWorkspace();
}
private static IWorkspaceRoot getWorkspaceRoot() {
return getWorkspace().getRoot();
}
private static void addJavaNature(String projectName) throws CoreException {
IProject project = getWorkspaceRoot().getProject(projectName);
IProjectDescription description = project.getDescription();
description.setNatureIds(new String[] { JavaCore.NATURE_ID });
project.setDescription(description, null);
}
static IJavaProject createJavaProject(final String projectName, final String[] sourceFolders,
final String projectOutput, final String compliance) throws CoreException {
final IJavaProject[] result = new IJavaProject[1];
IWorkspaceRunnable create = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
// create project
createProject(projectName);
// set java nature
addJavaNature(projectName);
// create classpath entries
IProject project = getWorkspaceRoot().getProject(projectName);
IPath projectPath = project.getFullPath();
int sourceLength = sourceFolders == null ? 0 : sourceFolders.length;
IClasspathEntry[] entries = new IClasspathEntry[sourceLength];
for (int i = 0; i < sourceLength; i++) {
IPath sourcePath = new Path(sourceFolders[i]);
int segmentCount = sourcePath.segmentCount();
if (segmentCount > 0) {
// create folder and its parents
IContainer container = project;
for (int j = 0; j < segmentCount; j++) {
IFolder folder = container.getFolder(new Path(sourcePath.segment(j)));
if (!folder.exists()) {
folder.create(true, true, null);
}
container = folder;
}
}
// create source entry
entries[i] = JavaCore.newSourceEntry(projectPath.append(sourcePath));
}
// create project's output folder
IPath outputPath = new Path(projectOutput);
if (outputPath.segmentCount() > 0) {
IFolder output = project.getFolder(outputPath);
if (!output.exists()) {
output.create(true, true, monitor);
}
}
// set classpath and output location
IJavaProject javaProject = JavaCore.create(project);
javaProject.setRawClasspath(entries, projectPath.append(outputPath), monitor);
// set compliance level options
if ("1.5".equals(compliance)) {
Map<String, String> options = new HashMap<String, String>();
options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_5);
options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_5);
options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_5);
javaProject.setOptions(options);
} else if ("1.6".equals(compliance)) {
Map<String, String> options = new HashMap<String, String>();
options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_6);
options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6);
options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_6);
javaProject.setOptions(options);
} else if ("1.7".equals(compliance)) {
Map<String, String> options = new HashMap<String, String>();
options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7);
options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7);
options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7);
javaProject.setOptions(options);
} else if ("1.8".equals(compliance)) {
Map<String, String> options = new HashMap<String, String>();
options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_8);
options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_8);
options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_8);
javaProject.setOptions(options);
}
result[0] = javaProject;
}
};
getWorkspace().run(create, null);
return result[0];
}
static void deleteProject(String projectName) throws CoreException {
IProject project = getProject(projectName);
if (project.exists() && !project.isOpen()) { // force opening so that
// project can be deleted
// without logging (see bug
// 23629)
project.open(null);
}
deleteResource(project);
}
private static void deleteResource(IResource resource) throws CoreException {
int retryCount = 0; // wait 1 minute at most
IStatus status = null;
while (++retryCount <= 6) {
status = WorkspaceUtilities.delete(resource);
if (status.isOK()) {
return;
}
System.gc();
}
throw new CoreException(status);
}
private static boolean isResourceDeleted(IResource resource) {
return !resource.isAccessible() && getParentChildResource(resource) == null;
}
private static IResource getParentChildResource(IResource resource) {
IContainer parent = resource.getParent();
if (parent == null || !parent.exists()) {
return null;
}
try {
IResource[] members = parent.members();
int length = members == null ? 0 : members.length;
if (length > 0) {
for (int i = 0; i < length; i++) {
if (members[i] == resource) {
return members[i];
} else if (members[i].equals(resource)) {
return members[i];
} else if (members[i].getFullPath().equals(resource.getFullPath())) {
return members[i];
}
}
}
} catch (CoreException ce) {
// skip
}
return null;
}
static IStatus delete(IResource resource) {
IStatus status = null;
try {
resource.delete(true, null);
if (isResourceDeleted(resource)) {
return Status.OK_STATUS;
}
} catch (CoreException e) {
status = e.getStatus();
}
boolean deleted = waitUntilResourceDeleted(resource);
if (deleted) {
return Status.OK_STATUS;
}
if (status != null) {
return status;
}
return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Cannot delete resource " + resource);
}
private static boolean waitUntilResourceDeleted(IResource resource) {
IPath location = resource.getLocation();
if (location == null) {
return false;
}
File file = location.toFile();
int count = 0;
int delay = 10; // ms
int maxRetry = DELETE_MAX_WAIT / delay;
int time = 0;
while (count < maxRetry) {
try {
count++;
Thread.sleep(delay);
time += delay;
if (time > DELETE_MAX_TIME)
DELETE_MAX_TIME = time;
if (resource.isAccessible()) {
try {
resource.delete(true, null);
if (isResourceDeleted(resource) && isFileDeleted(file)) {
// SUCCESS
return true;
}
} catch (CoreException e) {
// skip
}
}
if (isResourceDeleted(resource) && isFileDeleted(file)) {
// SUCCESS
return true;
}
// Increment waiting delay exponentially
if (count >= 10 && delay <= 100) {
count = 1;
delay *= 10;
maxRetry = DELETE_MAX_WAIT / delay;
if ((DELETE_MAX_WAIT % delay) != 0) {
maxRetry++;
}
}
} catch (InterruptedException ie) {
break; // end loop
}
}
return false;
}
private static boolean isFileDeleted(File file) {
return !file.exists() && getParentChildFile(file) == null;
}
private static File getParentChildFile(File file) {
File parent = file.getParentFile();
if (parent == null || !parent.exists()) {
return null;
}
File[] files = parent.listFiles();
int length = files == null ? 0 : files.length;
if (length > 0) {
for (int i = 0; i < length; i++) {
if (files[i] == file) {
return files[i];
} else if (files[i].equals(file)) {
return files[i];
} else if (files[i].getPath().equals(file.getPath())) {
return files[i];
}
}
}
return null;
}
}