blob: a4a5c5d9dcdc41787b6c7de73689a9b2c1b6d7bf [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.virgo.ide.eclipse.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.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
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.IResourceStatus;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
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.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.util.CoreUtility;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import org.eclipse.jdt.internal.ui.wizards.ClassPathDetector;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.wizards.JavaCapabilityConfigurationPage;
import org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageTwo;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation;
/**
* SpringSource Tool Suite Team - This class was copied from Eclipse 3.4 for use in 3.3-based distributions. Necessary
* changes included porting all the NewJavaProjectWizard messages from the NewWizardMessages utility class to
* NewJavaProjectWizardConstants.
*
* @deprecated As of release 2.0.0, STS only supports Eclipse 3.4 and above. Use {@link NewJavaProjectWizardPageTwo}
* instead. ----------------------------------------------------------------------------- The second page of
* the New Java project wizard. It allows to configure the build path and output location. As addition to
* the {@link JavaCapabilityConfigurationPage}, the wizard page does an early project creation (so that
* linked folders can be defined) and, if an existing external location was specified, detects the class
* path.
* <p>
* Clients may instantiate or subclass.
* </p>
* <p>
* <strong>EXPERIMENTAL</strong> This class or interface has been added as part of a work in progress. This
* API is under review and may still change when finalized. Please send your comments to bug 160985.
* </p>
* @since 3.4
*/
@SuppressWarnings("restriction")
@Deprecated
public class NewJavaProjectWizardPageTwoCOPY extends JavaCapabilityConfigurationPage {
private static final String FILENAME_PROJECT = ".project"; //$NON-NLS-1$
private static final String FILENAME_CLASSPATH = ".classpath"; //$NON-NLS-1$
private static URI getRealLocation(String projectName, URI location) {
if (location == null) { // inside workspace
try {
URI rootLocation = ResourcesPlugin.getWorkspace().getRoot().getLocationURI();
location = new URI(rootLocation.getScheme(), null, Path.fromPortableString(rootLocation.getPath()).append(projectName).toString(),
null);
} catch (URISyntaxException e) {
Assert.isTrue(false, "Can't happen"); //$NON-NLS-1$
}
}
return location;
}
/**
* Sets whether building automatically is enabled in the workspace or not and returns the old value.
*
* @param state <code>true</code> if automatically building is enabled, <code>false</code> otherwise
* @return the old state
* @throws CoreException thrown if the operation failed
*/
public static boolean setAutoBuilding(boolean state) throws CoreException {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceDescription desc = workspace.getDescription();
boolean isAutoBuilding = desc.isAutoBuilding();
if (isAutoBuilding != state) {
desc.setAutoBuilding(state);
workspace.setDescription(desc);
}
return isAutoBuilding;
}
private final NewJavaProjectWizardPageOneCOPY fFirstPage;
private URI fCurrProjectLocation; // null if location is platform location
private IProject fCurrProject;
private boolean fKeepContent;
private File fDotProjectBackup;
private File fDotClasspathBackup;
private Boolean fIsAutobuild;
private HashSet fOrginalFolders;
/**
* Constructor for the {@link NewJavaProjectWizardPageTwoCOPY}.
*
* @param mainPage the first page of the wizard
*/
public NewJavaProjectWizardPageTwoCOPY(NewJavaProjectWizardPageOneCOPY mainPage) {
this.fFirstPage = mainPage;
this.fCurrProjectLocation = null;
this.fCurrProject = null;
this.fKeepContent = false;
this.fDotProjectBackup = null;
this.fDotClasspathBackup = null;
this.fIsAutobuild = null;
}
private IStatus changeToNewProject() {
class UpdateRunnable implements IRunnableWithProgress {
public IStatus infoStatus = Status.OK_STATUS;
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
if (NewJavaProjectWizardPageTwoCOPY.this.fIsAutobuild == null) {
NewJavaProjectWizardPageTwoCOPY.this.fIsAutobuild = Boolean.valueOf(setAutoBuilding(false));
}
this.infoStatus = updateProject(monitor);
} catch (CoreException e) {
throw new InvocationTargetException(e);
} catch (OperationCanceledException e) {
throw new InterruptedException();
} finally {
monitor.done();
}
}
}
UpdateRunnable op = new UpdateRunnable();
try {
getContainer().run(true, false, new WorkspaceModifyDelegatingOperation(op));
return op.infoStatus;
} catch (InvocationTargetException e) {
final String title = NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_error_title;
final String message = NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_error_message;
ExceptionHandler.handle(e, getShell(), title, message);
} catch (InterruptedException e) {
// cancel pressed
}
return null;
}
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(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(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();
}
}
}
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, JavaUI.ID_PLUGIN, IStatus.ERROR,
Messages.format(NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_problem_backup, name), e);
throw new CoreException(status);
}
}
/**
* Creates the provisional project on which the wizard is working on. The provisional project is typically created
* when the page is entered the first time. The early project creation is required to configure linked folders.
*
* @return the provisional project
*/
protected IProject createProvisonalProject() {
IStatus status = changeToNewProject();
if (status != null && !status.isOK()) {
ErrorDialog.openError(getShell(), NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_error_title, null, status);
}
return this.fCurrProject;
}
private void deleteProjectFile(URI projectLocation) throws CoreException {
IFileStore file = EFS.getStore(projectLocation);
if (file.fetchInfo().exists()) {
IFileStore projectFile = file.getChild(FILENAME_PROJECT);
if (projectFile.fetchInfo().exists()) {
projectFile.delete(EFS.NONE, null);
}
}
}
private final void doRemoveProject(IProgressMonitor monitor) throws InvocationTargetException {
final boolean noProgressMonitor = this.fCurrProjectLocation == null; // inside
// workspace
if (monitor == null || noProgressMonitor) {
monitor = new NullProgressMonitor();
}
monitor.beginTask(NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_operation_remove, 3);
try {
try {
URI projLoc = this.fCurrProject.getLocationURI();
boolean removeContent = !this.fKeepContent && this.fCurrProject.isSynchronized(IResource.DEPTH_INFINITE);
if (!removeContent) {
restoreExistingFolders(projLoc);
}
this.fCurrProject.delete(removeContent, false, new SubProgressMonitor(monitor, 2));
restoreExistingFiles(projLoc, new SubProgressMonitor(monitor, 1));
} finally {
setAutoBuilding(this.fIsAutobuild.booleanValue()); // fIsAutobuild
// must
// be
// set
this.fIsAutobuild = null;
}
} catch (CoreException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
this.fCurrProject = null;
this.fKeepContent = false;
}
}
private boolean hasExistingContent(URI realLocation) throws CoreException {
IFileStore file = EFS.getStore(realLocation);
return file.fetchInfo().exists();
}
/**
* Evaluates the new build path and output folder according to the settings on the first page. The resulting build
* path is set by calling {@link #init(IJavaProject, IPath, IClasspathEntry[], boolean)}. Clients can override this
* method.
*
* @param javaProject the new project which is already created when this method is called.
* @param monitor the progress monitor
* @throws CoreException thrown when initializing the build path failed
*/
@SuppressWarnings("unchecked")
protected void initializeBuildPath(IJavaProject javaProject, IProgressMonitor monitor) throws CoreException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
monitor.beginTask(NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_monitor_init_build_path, 2);
try {
IClasspathEntry[] entries = null;
IPath outputLocation = null;
IProject project = javaProject.getProject();
if (this.fKeepContent) {
if (!project.getFile(FILENAME_CLASSPATH).exists()) {
final ClassPathDetector detector = new ClassPathDetector(this.fCurrProject, new SubProgressMonitor(monitor, 2));
entries = detector.getClasspath();
outputLocation = detector.getOutputLocation();
if (entries.length == 0) {
entries = null;
}
} else {
monitor.worked(2);
}
} else {
List cpEntries = new ArrayList();
IWorkspaceRoot root = project.getWorkspace().getRoot();
IClasspathEntry[] sourceClasspathEntries = this.fFirstPage.getSourceClasspathEntries();
for (IClasspathEntry sourceClasspathEntrie : sourceClasspathEntries) {
IPath path = sourceClasspathEntrie.getPath();
if (path.segmentCount() > 1) {
IFolder folder = root.getFolder(path);
CoreUtility.createFolder(folder, true, true, new SubProgressMonitor(monitor, 1));
}
cpEntries.add(sourceClasspathEntrie);
}
cpEntries.addAll(Arrays.asList(this.fFirstPage.getDefaultClasspathEntries()));
entries = (IClasspathEntry[]) cpEntries.toArray(new IClasspathEntry[cpEntries.size()]);
outputLocation = this.fFirstPage.getOutputLocation();
if (outputLocation.segmentCount() > 1) {
IFolder folder = root.getFolder(outputLocation);
CoreUtility.createDerivedFolder(folder, true, true, new SubProgressMonitor(monitor, 1));
}
}
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
init(javaProject, outputLocation, entries, false);
} finally {
monitor.done();
}
}
/**
* Called from the wizard on cancel.
*/
public void performCancel() {
if (this.fCurrProject != null) {
removeProvisonalProject();
}
}
/**
* Called from the wizard on finish.
*
* @param monitor the progress monitor
* @throws CoreException thrown when the project creation or configuration failed
* @throws InterruptedException thrown when the user cancelled the project creation
*/
@SuppressWarnings("unchecked")
public void performFinish(IProgressMonitor monitor) throws CoreException, InterruptedException {
try {
monitor.beginTask(NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_operation_create, 3);
if (this.fCurrProject == null) {
updateProject(new SubProgressMonitor(monitor, 1));
}
configureJavaProject(new SubProgressMonitor(monitor, 2));
if (!this.fKeepContent) {
String compliance = this.fFirstPage.getCompilerCompliance();
if (compliance != null) {
IJavaProject project = JavaCore.create(this.fCurrProject);
Map options = project.getOptions(false);
// JavaModelUtil.setCompilanceOptions(options, compliance);
JavaCore.setComplianceOptions(compliance, options);
JavaModelUtil.setDefaultClassfileOptions(options, compliance); // complete
// compliance
// options
project.setOptions(options);
}
}
} finally {
monitor.done();
this.fCurrProject = null;
if (this.fIsAutobuild != null) {
setAutoBuilding(this.fIsAutobuild.booleanValue());
this.fIsAutobuild = null;
}
}
}
@SuppressWarnings("unchecked")
private void rememberExisitingFolders(URI projectLocation) {
this.fOrginalFolders = new HashSet();
try {
IFileStore[] children = EFS.getStore(projectLocation).childStores(EFS.NONE, null);
for (IFileStore child : children) {
IFileInfo info = child.fetchInfo();
if (info.isDirectory() && info.exists() && !this.fOrginalFolders.contains(child.getName())) {
this.fOrginalFolders.add(child);
}
}
} catch (CoreException e) {
JavaPlugin.log(e);
}
}
private void rememberExistingFiles(URI projectLocation) throws CoreException {
this.fDotProjectBackup = null;
this.fDotClasspathBackup = null;
IFileStore file = EFS.getStore(projectLocation);
if (file.fetchInfo().exists()) {
IFileStore projectFile = file.getChild(FILENAME_PROJECT);
if (projectFile.fetchInfo().exists()) {
this.fDotProjectBackup = createBackup(projectFile, "project-desc"); //$NON-NLS-1$
}
IFileStore classpathFile = file.getChild(FILENAME_CLASSPATH);
if (classpathFile.fetchInfo().exists()) {
this.fDotClasspathBackup = createBackup(classpathFile, "classpath-desc"); //$NON-NLS-1$
}
}
}
/**
* Removes the provisional project. The provisional project is typically removed when the user cancels the wizard or
* goes back to the first page.
*/
protected void removeProvisonalProject() {
if (!this.fCurrProject.exists()) {
this.fCurrProject = null;
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 = NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_error_remove_title;
final String message = NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_error_remove_message;
ExceptionHandler.handle(e, getShell(), title, message);
} catch (InterruptedException e) {
// cancel pressed
}
}
private void restoreExistingFiles(URI projectLocation, IProgressMonitor monitor) throws CoreException {
int ticks = ((this.fDotProjectBackup != null ? 1 : 0) + (this.fDotClasspathBackup != null ? 1 : 0)) * 2;
monitor.beginTask("", ticks); //$NON-NLS-1$
try {
IFileStore projectFile = EFS.getStore(projectLocation).getChild(FILENAME_PROJECT);
projectFile.delete(EFS.NONE, new SubProgressMonitor(monitor, 1));
if (this.fDotProjectBackup != null) {
copyFile(this.fDotProjectBackup, projectFile, new SubProgressMonitor(monitor, 1));
}
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.ERROR,
NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_problem_restore_project, e);
throw new CoreException(status);
}
try {
IFileStore classpathFile = EFS.getStore(projectLocation).getChild(FILENAME_CLASSPATH);
classpathFile.delete(EFS.NONE, new SubProgressMonitor(monitor, 1));
if (this.fDotClasspathBackup != null) {
copyFile(this.fDotClasspathBackup, classpathFile, new SubProgressMonitor(monitor, 1));
}
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.ERROR,
NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_problem_restore_classpath, e);
throw new CoreException(status);
}
}
private void restoreExistingFolders(URI projectLocation) {
try {
IFileStore[] children = EFS.getStore(projectLocation).childStores(EFS.NONE, null);
for (IFileStore child : children) {
IFileInfo info = child.fetchInfo();
if (info.isDirectory() && info.exists() && !this.fOrginalFolders.contains(child)) {
child.delete(EFS.NONE, null);
this.fOrginalFolders.remove(child);
}
}
for (Iterator iterator = this.fOrginalFolders.iterator(); iterator.hasNext();) {
IFileStore deleted = (IFileStore) iterator.next();
deleted.mkdir(EFS.NONE, null);
}
} catch (CoreException e) {
JavaPlugin.log(e);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
*/
@Override
public void setVisible(boolean visible) {
boolean isShownFirstTime = visible && this.fCurrProject == null;
if (visible) {
if (isShownFirstTime) { // entering from the first page
createProvisonalProject();
}
} else {
if (getContainer().getCurrentPage() == this.fFirstPage) { // leaving
// back to
// the first
// page
removeProvisonalProject();
}
}
super.setVisible(visible);
if (isShownFirstTime) {
setFocus();
}
}
private final IStatus updateProject(IProgressMonitor monitor) throws CoreException, InterruptedException {
IStatus result = StatusInfo.OK_STATUS;
if (monitor == null) {
monitor = new NullProgressMonitor();
}
try {
monitor.beginTask(NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_operation_initialize, 7);
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
String projectName = this.fFirstPage.getProjectName();
this.fCurrProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
this.fCurrProjectLocation = this.fFirstPage.getProjectLocationURI();
URI realLocation = getRealLocation(projectName, this.fCurrProjectLocation);
this.fKeepContent = hasExistingContent(realLocation);
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
if (this.fKeepContent) {
rememberExistingFiles(realLocation);
rememberExisitingFolders(realLocation);
}
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
try {
createProject(this.fCurrProject, this.fCurrProjectLocation, new SubProgressMonitor(monitor, 2));
} catch (CoreException e) {
if (e.getStatus().getCode() == IResourceStatus.FAILED_READ_METADATA) {
result = new StatusInfo(IStatus.INFO, Messages.format(
NewJavaProjectWizardConstants.NewJavaProjectWizardPageTwo_DeleteCorruptProjectFile_message, e.getLocalizedMessage()));
deleteProjectFile(realLocation);
if (this.fCurrProject.exists()) {
this.fCurrProject.delete(true, null);
}
createProject(this.fCurrProject, this.fCurrProjectLocation, null);
} else {
throw e;
}
}
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
initializeBuildPath(JavaCore.create(this.fCurrProject), new SubProgressMonitor(monitor, 2));
configureJavaProject(new SubProgressMonitor(monitor, 3)); // create
// the
// Java
// project
// to
// allow
// the
// use
// of
// the
// new
// source
// folder
// page
} finally {
monitor.done();
}
return result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jdt.ui.wizards.JavaCapabilityConfigurationPage#useNewSourcePage ()
*/
@Override
protected final boolean useNewSourcePage() {
return true;
}
}