blob: 56bc02360bd360135cb5d0d8cb8400560ea2d62f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* 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
*
*******************************************************************************/
package org.eclipse.dltk.ui.wizards;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Observable;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
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.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.internal.core.ModelManager;
import org.eclipse.dltk.internal.core.builder.State;
import org.eclipse.dltk.internal.corext.util.Messages;
import org.eclipse.dltk.internal.ui.util.CoreUtility;
import org.eclipse.dltk.internal.ui.wizards.BuildpathDetector;
import org.eclipse.dltk.internal.ui.wizards.NewWizardMessages;
import org.eclipse.dltk.launching.IInterpreterInstall;
import org.eclipse.dltk.launching.ScriptRuntime;
import org.eclipse.dltk.launching.ScriptRuntime.DefaultInterpreterEntry;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.dltk.ui.PreferenceConstants;
import org.eclipse.dltk.ui.util.ExceptionHandler;
import org.eclipse.dltk.ui.wizards.ProjectWizardFirstPage.AbstractInterpreterGroup;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation;
/**
* As addition to the DLTKCapabilityConfigurationPage, the wizard does an early
* project creation (so that linked folders can be defined) and, if an existing
* external location was specified, offers to do a buildpath detection
*/
public abstract class ProjectWizardSecondPage extends
CapabilityConfigurationPage {
private static final String FILENAME_PROJECT = ".project"; //$NON-NLS-1$
private static final String FILENAME_BUILDPATH = ".buildpath"; //$NON-NLS-1$
private final ProjectWizardFirstPage fFirstPage;
private URI fCurrProjectLocation; // null if location is platform location
private IProject fCurrProject;
private boolean fKeepContent;
private File fDotProjectBackup;
private File fDotBuildpathBackup;
private Boolean fIsAutobuild;
/**
* Constructor for ScriptProjectWizardSecondPage.
*/
public ProjectWizardSecondPage(ProjectWizardFirstPage mainPage) {
fFirstPage = mainPage;
fCurrProjectLocation = null;
fCurrProject = null;
fKeepContent = false;
fDotProjectBackup = null;
fDotBuildpathBackup = null;
fIsAutobuild = null;
}
public ProjectWizardFirstPage getFirstPage() {
return fFirstPage;
}
protected boolean useNewSourcePage() {
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
*/
public void setVisible(boolean visible) {
if (visible) {
changeToNewProject();
} else {
removeProject();
}
super.setVisible(visible);
}
private void changeToNewProject() {
fKeepContent = fFirstPage.getDetect();
final IRunnableWithProgress op = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
try {
if (fIsAutobuild == null) {
fIsAutobuild = Boolean.valueOf(CoreUtility
.enableAutoBuild(false));
}
updateProject(monitor);
} catch (CoreException e) {
throw new InvocationTargetException(e);
} catch (OperationCanceledException e) {
throw new InterruptedException();
} finally {
monitor.done();
}
}
};
try {
getContainer().run(true, false,
new WorkspaceModifyDelegatingOperation(op));
} catch (InvocationTargetException e) {
final String title = NewWizardMessages.ScriptProjectWizardSecondPage_error_title;
final String message = NewWizardMessages.ScriptProjectWizardSecondPage_error_message;
ExceptionHandler.handle(e, getShell(), title, message);
} catch (InterruptedException e) {
// cancel pressed
}
}
final void updateProject(IProgressMonitor monitor) throws CoreException,
InterruptedException {
fCurrProject = fFirstPage.getProjectHandle();
fCurrProjectLocation = getProjectLocationURI();
if (monitor == null) {
monitor = new NullProgressMonitor();
}
try {
monitor
.beginTask(
NewWizardMessages.ScriptProjectWizardSecondPage_operation_initialize,
70);
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
URI realLocation = fCurrProjectLocation;
if (fCurrProjectLocation == null) { // inside workspace
try {
URI rootLocation = ResourcesPlugin.getWorkspace().getRoot()
.getLocationURI();
realLocation = new URI(rootLocation.getScheme(), null, Path
.fromPortableString(rootLocation.getPath()).append(
fCurrProject.getName()).toString(), null);
} catch (URISyntaxException e) {
Assert.isTrue(false, "Can't happen"); //$NON-NLS-1$
}
}
rememberExistingFiles(realLocation);
createProject(fCurrProject, fCurrProjectLocation,
new SubProgressMonitor(monitor, 20));
IBuildpathEntry[] entries = null;
if (fFirstPage.getDetect()) {
if (!fCurrProject.getFile(FILENAME_BUILDPATH).exists()) {
IDLTKLanguageToolkit toolkit = DLTKLanguageManager
.getLanguageToolkit(getScriptNature());
final BuildpathDetector detector = createBuildpathDetector(
monitor, toolkit);
entries = detector.getBuildpath();
} else {
monitor.worked(20);
}
} else if (fFirstPage.isSrc()) {
IPreferenceStore store = getPreferenceStore();
IPath srcPath = new Path(store
.getString(PreferenceConstants.SRC_SRCNAME));
if (srcPath.segmentCount() > 0) {
IFolder folder = fCurrProject.getFolder(srcPath);
CoreUtility.createFolder(folder, true, true,
new SubProgressMonitor(monitor, 10));
} else {
monitor.worked(10);
}
if (srcPath.segmentCount() > 0) {
IFolder folder = fCurrProject.getFolder(srcPath);
CoreUtility.createFolder(folder, true, true,
new SubProgressMonitor(monitor, 10));
} else {
monitor.worked(10);
}
final IPath projectPath = fCurrProject.getFullPath();
// configure the buildpath entries, including the default
// InterpreterEnvironment library.
List cpEntries = new ArrayList();
cpEntries.add(DLTKCore.newSourceEntry(projectPath
.append(srcPath)));
IBuildpathEntry[] entrys = getDefaultBuildpathEntry();
if (entrys != null) {
cpEntries.addAll(Arrays.asList(entrys));
}
entries = (IBuildpathEntry[]) cpEntries
.toArray(new IBuildpathEntry[cpEntries.size()]);
} else {
IPath projectPath = fCurrProject.getFullPath();
List cpEntries = new ArrayList();
cpEntries.add(DLTKCore.newSourceEntry(projectPath));
IBuildpathEntry[] entrys = getDefaultBuildpathEntry();
if (entrys != null) {
cpEntries.addAll(Arrays.asList(entrys));
}
entries = (IBuildpathEntry[]) cpEntries
.toArray(new IBuildpathEntry[cpEntries.size()]);
monitor.worked(20);
}
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
init(DLTKCore.create(fCurrProject), entries, false);
configureScriptProject(new SubProgressMonitor(monitor, 30)); // create
/*
* the script project to allow the use of the new source folder page
*/
} finally {
monitor.done();
}
}
protected BuildpathDetector createBuildpathDetector(
IProgressMonitor monitor, IDLTKLanguageToolkit toolkit)
throws CoreException {
BuildpathDetector detector = new BuildpathDetector(fCurrProject,
toolkit);
detector.detectBuildpath(new SubProgressMonitor(monitor, 20));
return detector;
}
protected abstract IPreferenceStore getPreferenceStore();
private URI getProjectLocationURI() throws CoreException {
if (fFirstPage.isInWorkspace()) {
return null;
}
return fFirstPage.getLocationURI();
}
private IBuildpathEntry[] getDefaultBuildpathEntry() {
IBuildpathEntry defaultPath = ScriptRuntime
.getDefaultInterpreterContainerEntry();
IPath InterpreterEnvironmentContainerPath = new Path(
ScriptRuntime.INTERPRETER_CONTAINER);
IInterpreterInstall inst = fFirstPage.getInterpreter();
if (inst != null) {
IPath newPath = InterpreterEnvironmentContainerPath.append(
inst.getInterpreterInstallType().getId()).append(
inst.getName());
return new IBuildpathEntry[] { DLTKCore.newContainerEntry(newPath) };
}
if (defaultPath != null)
return new IBuildpathEntry[] { defaultPath };
return null;
}
private void rememberExistingFiles(URI projectLocation)
throws CoreException {
fDotProjectBackup = null;
fDotBuildpathBackup = null;
IFileStore file = EFS.getStore(projectLocation);
if (file.fetchInfo().exists()) {
IFileStore projectFile = file.getChild(FILENAME_PROJECT);
if (projectFile.fetchInfo().exists()) {
fDotProjectBackup = createBackup(projectFile, "project-desc"); //$NON-NLS-1$
}
IFileStore buildpathFile = file.getChild(FILENAME_BUILDPATH);
if (buildpathFile.fetchInfo().exists()) {
fDotBuildpathBackup = createBackup(buildpathFile,
"buildpath-desc"); //$NON-NLS-1$
}
}
}
private void restoreExistingFiles(URI projectLocation,
IProgressMonitor monitor) throws CoreException {
int ticks = ((fDotProjectBackup != null ? 1 : 0) + (fDotBuildpathBackup != null ? 1
: 0)) * 2;
monitor.beginTask("", ticks); //$NON-NLS-1$
try {
if (fDotProjectBackup != null) {
IFileStore projectFile = EFS.getStore(projectLocation)
.getChild(FILENAME_PROJECT);
projectFile
.delete(EFS.NONE, new SubProgressMonitor(monitor, 1));
copyFile(fDotProjectBackup, projectFile,
new SubProgressMonitor(monitor, 1));
}
} catch (IOException e) {
IStatus status = new Status(
IStatus.ERROR,
DLTKUIPlugin.PLUGIN_ID,
IStatus.ERROR,
NewWizardMessages.ScriptProjectWizardSecondPage_problem_restore_project,
e);
throw new CoreException(status);
}
try {
if (fDotBuildpathBackup != null) {
IFileStore buildpathFile = EFS.getStore(projectLocation)
.getChild(FILENAME_BUILDPATH);
buildpathFile.delete(EFS.NONE, new SubProgressMonitor(monitor,
1));
copyFile(fDotBuildpathBackup, buildpathFile,
new SubProgressMonitor(monitor, 1));
}
} catch (IOException e) {
IStatus status = new Status(
IStatus.ERROR,
DLTKUIPlugin.PLUGIN_ID,
IStatus.ERROR,
NewWizardMessages.ScriptProjectWizardSecondPage_problem_restore_buildpath,
e);
throw new CoreException(status);
}
}
private File createBackup(IFileStore source, String name)
throws CoreException {
try {
File bak = File.createTempFile("eclipse-" + name, ".bak"); //$NON-NLS-1$//$NON-NLS-2$
copyFile(source, bak);
return bak;
} catch (IOException e) {
IStatus status = new Status(
IStatus.ERROR,
DLTKUIPlugin.PLUGIN_ID,
IStatus.ERROR,
Messages
.format(
NewWizardMessages.ScriptProjectWizardSecondPage_problem_backup,
name), e);
throw new CoreException(status);
}
}
private void copyFile(IFileStore source, File target) throws IOException,
CoreException {
InputStream is = source.openInputStream(EFS.NONE, null);
FileOutputStream os = new FileOutputStream(target);
copyFile(is, os);
}
private void copyFile(File source, IFileStore target,
IProgressMonitor monitor) throws IOException, CoreException {
FileInputStream is = new FileInputStream(source);
OutputStream os = target.openOutputStream(EFS.NONE, monitor);
copyFile(is, os);
}
private void copyFile(InputStream is, OutputStream os) throws IOException {
try {
byte[] buffer = new byte[8192];
while (true) {
int bytesRead = is.read(buffer);
if (bytesRead == -1)
break;
os.write(buffer, 0, bytesRead);
}
} finally {
try {
is.close();
} finally {
os.close();
}
}
}
/**
* Called from the wizard on finish.
*/
public void performFinish(IProgressMonitor monitor) throws CoreException,
InterruptedException {
try {
monitor
.beginTask(
NewWizardMessages.ScriptProjectWizardSecondPage_operation_create,
3);
if (fCurrProject == null) {
updateProject(new SubProgressMonitor(monitor, 1));
}
configureScriptProject(new SubProgressMonitor(monitor, 2));
if (!fKeepContent) {
if (DLTKCore.DEBUG) {
System.err
.println("Add compiler compilance options here..."); //$NON-NLS-1$
}
// String compliance= fFirstPage.getCompilerCompliance();
// if (compliance != null) {
// IScriptProject project= DLTKCore.create(fCurrProject);
// Map options= project.getOptions(false);
// ModelUtil.setCompilanceOptions(options, compliance);
// project.setOptions(options);
// }
}
// Not rebuild project external libraries if exist project with same
// interpreter.
IInterpreterInstall projectInterpreter = this.fFirstPage
.getInterpreter();
if (projectInterpreter == null) {
Observable observable = fFirstPage
.getInterpreterGroupObservable();
String nature = null;
if (observable != null
&& observable instanceof AbstractInterpreterGroup) {
AbstractInterpreterGroup gr = (AbstractInterpreterGroup) observable;
nature = gr.getCurrentLanguageNature();
}
if (nature != null) {
String environment = fFirstPage.getEnvironment().getId();
DefaultInterpreterEntry entry = new DefaultInterpreterEntry(
nature, environment);
projectInterpreter = ScriptRuntime
.getDefaultInterpreterInstall(entry);
}
}
if (projectInterpreter != null) {
State lastState = (State) ModelManager.getModelManager()
.getLastBuiltState(fCurrProject, monitor);
if (lastState == null) {
lastState = new State(fCurrProject);
}
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
.getProjects();
for (int i = 0; i < projects.length; i++) {
if (projects[i].isAccessible()
&& DLTKLanguageManager.hasScriptNature(projects[i])) {
IScriptProject scriptProject = DLTKCore
.create(projects[i]);
IInterpreterInstall install = ScriptRuntime
.getInterpreterInstall(scriptProject);
if (projectInterpreter.equals(install)) {
// We found project with same interpreter.
State state = (State) ModelManager
.getModelManager().getLastBuiltState(
projects[i], monitor);
if (state != null) {
lastState.getExternalFolders().addAll(
state.getExternalFolders());
}
}
}
}
lastState.setNoCleanExternalFolders();
ModelManager.getModelManager().setLastBuiltState(fCurrProject,
lastState);
}
// Locate projects with same interpreter.
} finally {
monitor.done();
fCurrProject = null;
if (fIsAutobuild != null) {
CoreUtility.enableAutoBuild(fIsAutobuild.booleanValue());
fIsAutobuild = null;
}
}
}
private void removeProject() {
if (fCurrProject == null || !fCurrProject.exists()) {
return;
}
IRunnableWithProgress op = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
doRemoveProject(monitor);
}
};
try {
getContainer().run(true, true,
new WorkspaceModifyDelegatingOperation(op));
} catch (InvocationTargetException e) {
final String title = NewWizardMessages.ScriptProjectWizardSecondPage_error_remove_title;
final String message = NewWizardMessages.ScriptProjectWizardSecondPage_error_remove_message;
ExceptionHandler.handle(e, getShell(), title, message);
} catch (InterruptedException e) {
// cancel pressed
}
}
final void doRemoveProject(IProgressMonitor monitor)
throws InvocationTargetException {
final boolean noProgressMonitor = (fCurrProjectLocation == null); // inside
// workspace
if (monitor == null || noProgressMonitor) {
monitor = new NullProgressMonitor();
}
monitor
.beginTask(
NewWizardMessages.ScriptProjectWizardSecondPage_operation_remove,
3);
try {
try {
URI projLoc = fCurrProject.getLocationURI();
boolean removeContent = !fKeepContent
&& fCurrProject
.isSynchronized(IResource.DEPTH_INFINITE);
fCurrProject.delete(removeContent, false,
new SubProgressMonitor(monitor, 2));
restoreExistingFiles(projLoc,
new SubProgressMonitor(monitor, 1));
} finally {
CoreUtility.enableAutoBuild(fIsAutobuild.booleanValue()); // fIsAutobuild
// must
// be
// set
fIsAutobuild = null;
}
} catch (CoreException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
fCurrProject = null;
fKeepContent = false;
}
}
/**
* Called from the wizard on cancel.
*/
public void performCancel() {
removeProject();
}
public IProject getCurrProject() {
return fCurrProject;
}
}