/*******************************************************************************
* Copyright (c) 2008 Pierre-Antoine Grégoire.
* 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:
* Pierre-Antoine Grégoire - initial API and implementation
*******************************************************************************/
package org.org.eclipse.cheatsheet.commands.internal.jobs;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Proxy;
import java.net.URISyntaxException;
import java.net.URL;
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.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.org.eclipse.cheatsheet.commands.handlers.ModeParameterValues;
import org.org.eclipse.core.utils.platform.jobs.BatchSimilarRule;
import org.org.eclipse.core.utils.platform.tools.ArchivesToolBox;
import org.org.eclipse.core.utils.platform.tools.IOToolBox;
import org.org.eclipse.core.utils.platform.wizards.StatusInfo;
public class CreateProjectInWorkspaceJob extends Job {
private static String JOB_ID = "CheatSheet helper: create project in workspace";
private URL fileUrl;
private String pathInArchive;
private String targetProjectName;
private String mode;
private String customSuffix;
public CreateProjectInWorkspaceJob(URL fileUrl, String pathInArchive, String targetProjectName, String mode, String customSuffix) {
super(JOB_ID);
this.fileUrl = fileUrl;
this.pathInArchive = pathInArchive;
this.targetProjectName = targetProjectName;
this.mode = mode;
this.customSuffix = customSuffix;
this.setPriority(Job.LONG);
this.setUser(true);
this.setRule(new BatchSimilarRule(CheatSheetJobs.JOB_FAMILY));
}
@Override
protected IStatus run(IProgressMonitor monitor) {
IStatus result = new StatusInfo(IStatus.OK, "Project created successfully.");
try {
if (!projectExistsInWorkspace(targetProjectName)) {
decompressRemoteProjectArchiveIntoWorkspace(fileUrl, pathInArchive, targetProjectName, monitor);
} else {
if (mode.equals(ModeParameterValues.REPLACE)) {
decompressRemoteProjectArchiveIntoWorkspace(fileUrl, pathInArchive, targetProjectName, monitor);
} else if (mode.equals(ModeParameterValues.SUFFIX)) {
String projectName = targetProjectName;
if (customSuffix != null) {
projectName = suffixWithCustomSuffix(targetProjectName);
} else {
projectName = suffixWithNumber(targetProjectName);
}
decompressRemoteProjectArchiveIntoWorkspace(fileUrl, pathInArchive, projectName, monitor);
} else if (mode.equals(ModeParameterValues.SKIP)) {
// Skip ;)
}
}
monitor.worked(100);
} catch (Throwable e) {
monitor.setCanceled(true);
result = new StatusInfo(IStatus.ERROR, "A problem occured while creating project:\n" + e.getMessage());
} finally {
monitor.done();
}
return result;
}
private String suffixWithCustomSuffix(String projectName) {
String result = projectName + customSuffix;
if (new File(result).exists()) {
result = suffixWithNumber(result);
}
return result;
}
private String suffixWithNumber(String projectName) {
int i = 1;
String result = projectName + "(" + (i++) + ")";
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IResource member = workspaceRoot.findMember(result);
while (member != null && member.getAdapter(IProject.class) != null) {
result = projectName + "(" + (i++) + ")";
member = workspaceRoot.findMember(result);
}
return result;
}
private void decompressRemoteProjectArchiveIntoWorkspace(URL fileUrl, String pathInArchive, String targetProjectName, IProgressMonitor monitor) throws IOException, CoreException, URISyntaxException {
monitor.beginTask("Importing...", 1000);
monitor.worked(100);
File tmpFile = File.createTempFile("cheatsheets", ".zipfile");
downloadToLocalFile(tmpFile, fileUrl, IOToolBox.determineProxy(fileUrl), monitor);
IProject project = createProjectShellInWorkspace(targetProjectName, monitor);
File targetFolder = project.getLocation().makeAbsolute().toFile();
decompressArchive(tmpFile, targetFolder, pathInArchive, monitor);
project.open(new SubProgressMonitor(monitor, 100));
project.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 100));
// FIXME when possible, as this could be broken by future releases...
// next step is necessary in order to have an up-to-date project name in the project's description (.project file)
IProjectDescription projectDescription = project.getDescription();
projectDescription.setName("");// project description has to have a difference from current one, but name will be ignored and replaced by project's FS name.
project.setDescription(projectDescription, new SubProgressMonitor(monitor, 100));
}
private static void decompressArchive(File tmpFile, File targetFolder, String pathInArchive, IProgressMonitor monitor) throws IOException {
monitor.subTask("Deflating archive.");
ArchivesToolBox.decompressArchiveSubPartTo(tmpFile, targetFolder, pathInArchive);
monitor.worked(100);
}
private static IProject createProjectShellInWorkspace(String targetProjectName, IProgressMonitor monitor) throws CoreException {
monitor.subTask("Creating project in workspace");
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
IProject project = root.getProject(targetProjectName);
if (!project.exists()) {
project.create(new SubProgressMonitor(monitor, 100));
}
if (project.isOpen()) {
project.close(new SubProgressMonitor(monitor, 100));
}
monitor.worked(200);
return project;
}
private boolean projectExistsInWorkspace(String targetProjectName) {
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IResource member = workspaceRoot.findMember(targetProjectName);
return (member != null && member.getAdapter(IProject.class) != null);
}
private static void downloadToLocalFile(File targetFile, URL requestedURL, Proxy proxy, IProgressMonitor monitor) throws IOException {
monitor.subTask("Downloading remote archived project to: " + targetFile.getAbsolutePath());
InputStream is = null;
FileOutputStream out = null;
try {
is = open(requestedURL, proxy);
targetFile.createNewFile();
out = new FileOutputStream(targetFile);
byte[] buf = new byte[1024]; // 1K buffer
int bytesRead;
while ((bytesRead = is.read(buf)) != -1) {
out.write(buf, 0, bytesRead);
}
monitor.worked(100);
} finally {
close(is);
close(out);
}
}
private static void close(InputStream in) {
if (in != null) {
try {
in.close();
} catch (IOException e1) {
// ignore.
}
}
}
private static void close(OutputStream out) {
if (out != null) {
try {
out.close();
} catch (IOException e1) {
// ignore.
}
}
}
private static InputStream open(URL url, Proxy proxy) throws IOException {
InputStream inputStream = null;
if (proxy != null) {
inputStream = url.openConnection(proxy).getInputStream();
} else {
inputStream = url.openConnection().getInputStream();
}
return inputStream;
}
}