Java tutorial
/******************************************************************************* * Copyright (c) 2004, 2009 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 * * Contributors: * IBM Corporation - initial API and implementation * Red Hat, Inc - extensive changes to allow importing of Archive Files * Philippe Ombredanne (pombredanne@nexb.com) * - Bug 101180 [Import/Export] Import Existing Project into Workspace default widget is back button , should be text field * Martin Oberhuber (martin.oberhuber@windriver.com) * - Bug 187318[Wizards] "Import Existing Project" loops forever with cyclic symbolic links * Remy Chi Jian Suen (remy.suen@gmail.com) * - Bug 210568 [Import/Export] [Import/Export] - Refresh button does not update list of projects * Andrei Loskutov - bug fixes * - Stripped down all what we do not need in Mercurial *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; 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.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.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IInputValidator; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.IWizard; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.dialogs.IOverwriteQuery; import org.eclipse.ui.dialogs.WorkingSetGroup; import org.eclipse.ui.statushandlers.StatusManager; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * The ProjectsImportPage is the page that allows the user to import * projects from a particular location. * * see org.eclipse.ui.internal.wizards.datatransfer.WizardProjectsImportPage */ public class ProjectsImportPage extends WizardPage implements IOverwriteQuery { private static final String DESCRIPTION = "Select projects to import into the workspace. " + "Checked projects will be imported. Double click on project to change project name."; /** * The name of the folder containing metadata information for the workspace. */ public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$ /** * Enable the possibility of checking both main project and * subprojects. If that property is false the main project * and the subproject are mutually exclusive. * Very untested feature!. * TODO: Set to true and test so that if there is a .project in root * there is still the option of importing sub-projects (with the * constraint that ancestors can't both be imported(?)) */ private static final boolean ENABLE_NESTED_CHECK = false; private final class ProjectLabelProvider extends LabelProvider implements IColorProvider { @Override public String getText(Object element) { return ((ProjectRecord) element).getProjectLabel(); } public Color getBackground(Object element) { return null; } public Color getForeground(Object element) { ProjectRecord projectRecord = (ProjectRecord) element; if (projectRecord.hasConflicts) { return getShell().getDisplay().getSystemColor(SWT.COLOR_GRAY); } return null; } } /** * The project name is initialized the first available of: * - The name in the project file * - The name of the last segment of the path * - The name of the project file with integers appended. */ private static class ProjectRecord { private final File projectSystemFile; final IProjectDescription description; String projectName; String fallbackProjectName; boolean hasConflicts; /** * Create a record for a project based on the info in the file. * * @param file */ ProjectRecord(File file, ProjectNameScope scope) { projectSystemFile = file; description = createDescription(); projectName = scope.getAvailableName(description.getName(), fallbackProjectName); } /** * Creates project description based on the projectFile. * @return never null */ private IProjectDescription createDescription() { IProjectDescription tmpDescription; // If we don't have the project name try again IWorkspace workspace = ResourcesPlugin.getWorkspace(); if (projectSystemFile.isDirectory()) { fallbackProjectName = projectSystemFile.getName(); tmpDescription = workspace.newProjectDescription(fallbackProjectName); // check if the directory matches the default location? // if yes, should NOT set location, as in the "else" branch below File wsRoot = workspace.getRoot().getLocation().toFile(); if (!wsRoot.equals(projectSystemFile) && !wsRoot.equals(projectSystemFile.getParentFile())) { tmpDescription.setLocation(new Path(projectSystemFile.getAbsolutePath())); } } else { IPath path = new Path(projectSystemFile.getPath()); fallbackProjectName = path.segment(path.segmentCount() - 2); try { tmpDescription = workspace.loadProjectDescription(path); } catch (CoreException e) { // no good, couldn't load tmpDescription = workspace.newProjectDescription(fallbackProjectName); tmpDescription.setLocation(path.removeLastSegments(1)); } if (isDefaultLocation(path)) { // for some strange reasons (bug?) Eclipse disallows to create // projects inside the workspace IF the project description has // a location attribute set... tmpDescription.setLocation(null); } } return tmpDescription; } /** * Returns whether the given project description file path is in the * default location for a project * * @param path * The path to examine * @return Whether the given path is the default location for a project */ private static boolean isDefaultLocation(IPath path) { // The project description file must at least be within the project, // which is within the workspace location if (path.segmentCount() < 2) { return false; } return path.removeLastSegments(2).toFile().equals(Platform.getLocation().toFile()); } /** * Get the name of the project * * @return String */ public String getProjectName() { return projectName; } public File getDataDir() { return projectSystemFile.isDirectory() ? projectSystemFile : projectSystemFile.getParentFile(); } /** * Gets the label to be used when rendering this project record in the * UI. * * @return String the label */ public String getProjectLabel() { String path = projectSystemFile.isDirectory() ? projectSystemFile.getAbsolutePath() : projectSystemFile.getParent(); return projectName + " (" + path + ")"; } } private CheckboxTreeViewer projectsList; private ProjectRecord[] selectedProjects; private IProject[] wsProjects; // The last selected path to minimize searches private String lastPath; // The last time that the file or folder at the selected path was modified // to mimize searches private long lastModified; private WorkingSetGroup workingSetGroup; private List<IProject> createdProjects; /** initial repo path */ private File repositoryRoot; /** cloned repo destination path */ private File destinationDir; private Text destinationDirText; private boolean destinationSelectionEnabled; /** * Creates a new project creation wizard page. */ public ProjectsImportPage(String pageName) { super(pageName); selectedProjects = new ProjectRecord[0]; setPageComplete(false); setTitle("Import Projects"); setDescription(DESCRIPTION); } public void setDestinationSelectionEnabled(boolean enabled) { this.destinationSelectionEnabled = enabled; } private boolean isMainProjectActive() { /* The main project element could be used if and only if * 1) tryToUseMainProject is set * and * 2) no destination selection is enabled: * the main project is available just when cloning the remote repository; * otherwise is possible create a project with a nested project in his root, * in these cases the behavior is unpredictable and undocumented. * or * 3) There is just one project: the main project */ return !this.destinationSelectionEnabled || selectedProjects.length < 2; } public void createControl(Composite parent) { initializeDialogUnits(parent); Composite workArea = new Composite(parent, SWT.NONE); setControl(workArea); workArea.setLayout(new GridLayout()); workArea.setLayoutData( new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL)); if (destinationSelectionEnabled) { createRootSelection(workArea); } createProjectsList(workArea); createWorkingSetGroup(workArea); restoreWidgetValues(); Dialog.applyDialogFont(workArea); } private void createRootSelection(Composite workArea) { Composite selectComposite = new Composite(workArea, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 3; layout.marginWidth = 0; layout.makeColumnsEqualWidth = false; selectComposite.setLayout(layout); // GridData GridData data = new GridData(GridData.FILL_HORIZONTAL); selectComposite.setLayoutData(data); SWTWidgetHelper.createLabel(selectComposite, "Root directory:"); destinationDirText = SWTWidgetHelper.createTextField(selectComposite); Button browseButton = SWTWidgetHelper.createPushButton(selectComposite, "Browse...", 1); browseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { String dir; if (destinationDir != null && !destinationDirText.getText().equals(destinationDir.getAbsolutePath())) { dir = destinationDirText.getText(); } else { DirectoryDialog dialog = new DirectoryDialog(getShell()); dialog.setFilterPath(destinationDirText.getText()); dialog.setMessage("Select root directory"); dir = dialog.open(); } if (dir != null) { dir = dir.trim(); setInitialSelection(new File(dir)); } } }); } private void fixFinishState() { setPageComplete(projectsList.getCheckedElements().length > 0); } private void createWorkingSetGroup(Composite workArea) { String[] workingSetIds = new String[] { "org.eclipse.ui.resourceWorkingSetPage", //$NON-NLS-1$ "org.eclipse.jdt.ui.JavaWorkingSetPage" }; //$NON-NLS-1$ workingSetGroup = new WorkingSetGroup(workArea, null, workingSetIds); } /** * Create the checkbox list for the found projects. */ private void createProjectsList(Composite workArea) { Group listComposite = new Group(workArea, SWT.NONE); listComposite.setText("Projects"); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginWidth = 0; layout.makeColumnsEqualWidth = false; listComposite.setLayout(layout); listComposite.setLayoutData( new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH)); projectsList = new CheckboxTreeViewer(listComposite, SWT.BORDER); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); gridData.widthHint = convertWidthInCharsToPixels(25); gridData.heightHint = convertHeightInCharsToPixels(10); projectsList.getControl().setLayoutData(gridData); projectsList.setContentProvider(new ITreeContentProvider() { public Object[] getChildren(Object parentElement) { if (hasChildren(parentElement)) { return getSubProjectRecords(); } return null; } public Object[] getElements(Object inputElement) { if (selectedProjects.length == 0) { return new Object[0]; } if (isMainProjectActive()) { Object[] root = new Object[1]; root[0] = selectedProjects[0]; return root; } return getSubProjectRecords(); } public boolean hasChildren(Object element) { return isMainProjectActive() && (element == selectedProjects[0]) && (selectedProjects.length > 1); } public Object getParent(Object element) { return (isMainProjectActive() && (element != selectedProjects[0])) ? selectedProjects[0] : null; } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } }); final ProjectLabelProvider labelProvider = new ProjectLabelProvider(); projectsList.setLabelProvider(labelProvider); projectsList.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { ProjectRecord element = (ProjectRecord) event.getElement(); if (!element.hasConflicts && event.getChecked()) { enableProject(element); } else { disableProject(element); } } }); projectsList.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); Object element = selection.getFirstElement(); if (!(element instanceof ProjectRecord)) { return; } final ProjectRecord record = (ProjectRecord) element; IInputValidator validator = new IInputValidator() { public String isValid(String newText) { ProjectRecord[] projects = selectedProjects; for (ProjectRecord pr : projects) { if (pr != record && pr.projectName.equals(newText)) { return "A project with same name already exists"; } } if (isProjectInWorkspace(newText)) { return "A project with same name already exists"; } if (newText.length() == 0) { return "Project name cannot be empty"; } return null; } }; InputDialog input = new InputDialog(getShell(), "Clone repository", "Change project name for imported project", record.projectName, validator); int ok = input.open(); if (ok == Window.OK) { record.projectName = input.getValue(); record.hasConflicts = isProjectInWorkspace(record.projectName); } validateSelectedProjects(); if (!record.hasConflicts) { enableProject(record); } else { disableProject(record); } fixFinishState(); projectsList.refresh(true); } }); projectsList.setInput(this); projectsList.setComparator(new ViewerComparator()); createSelectionButtons(listComposite); } /** * Create the selection buttons in the listComposite. * * @param listComposite */ private void createSelectionButtons(Composite listComposite) { Composite buttonsComposite = new Composite(listComposite, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; buttonsComposite.setLayout(layout); buttonsComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); Button selectAll = new Button(buttonsComposite, SWT.PUSH); selectAll.setText("&Select All"); selectAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { enableAllProjects(); } }); Dialog.applyDialogFont(selectAll); setButtonLayoutData(selectAll); Button deselectAll = new Button(buttonsComposite, SWT.PUSH); deselectAll.setText("&Deselect All"); deselectAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { disableAllProjects(); } }); Dialog.applyDialogFont(deselectAll); setButtonLayoutData(deselectAll); Button refresh = new Button(buttonsComposite, SWT.PUSH); refresh.setText("R&efresh"); refresh.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (destinationDir != null) { updateProjectsList(destinationDir.getAbsolutePath()); } } }); Dialog.applyDialogFont(refresh); setButtonLayoutData(refresh); } /** * Set the focus on path fields when page becomes visible. */ @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { IWizardPage previousPage = getPreviousPage(); if (previousPage instanceof ClonePage) { ClonePage page = (ClonePage) previousPage; File directory = page.getDestinationDirectory(); setInitialSelection(directory); } if (previousPage instanceof SelectRevisionPage) { SelectRevisionPage page = (SelectRevisionPage) previousPage; File directory = page.getHgRoot(); setInitialSelection(directory); } else if (getWizard() instanceof ImportProjectsFromRepoWizard) { final ImportProjectsFromRepoWizard impWizard = (ImportProjectsFromRepoWizard) getWizard(); if (impWizard.getInitialPath() != null) { impWizard.getShell().getDisplay().asyncExec(new Runnable() { public void run() { setInitialSelection(impWizard.getInitialPath()); } }); } } } } /** * Update the list of projects based on path. * * @param path */ private void updateProjectsList(final String path) { // on an empty path empty selectedProjects if (path == null || path.length() == 0) { setMessage(DESCRIPTION); selectedProjects = new ProjectRecord[0]; projectsList.refresh(true); projectsList.setCheckedElements(selectedProjects); fixFinishState(); lastPath = path; return; } repositoryRoot = new File(path); long modified = repositoryRoot.lastModified(); if (path.equals(lastPath) && lastModified == modified) { // since the file/folder was not modified and the path did not // change, no refreshing is required return; } lastPath = path; lastModified = modified; try { getContainer().run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { ProjectNameScope namer = new ProjectNameScope(); monitor.beginTask("Searching for projects", 100); selectedProjects = new ProjectRecord[0]; Collection<File> files = new ArrayList<File>(); monitor.worked(10); if (repositoryRoot.isDirectory()) { if (!collectProjectFilesFromDirectory(files, repositoryRoot, null, monitor, false)) { return; } Iterator<File> filesIterator = files.iterator(); List<ProjectRecord> prj = new ArrayList<ProjectRecord>(); monitor.worked(50); monitor.subTask("Processing results"); if (filesIterator.hasNext()) { /* Check if the first project is the root */ File file = filesIterator.next(); File dir = file.getParentFile(); if (dir.isDirectory() && dir.equals(destinationDir)) { prj.add(new ProjectRecord(file, namer)); } else { filesIterator = files.iterator(); /* reset iterator */ } } if (prj.isEmpty()) { prj.add(new ProjectRecord(destinationDir, namer)); } while (filesIterator.hasNext()) { File file = filesIterator.next(); prj.add(new ProjectRecord(file, namer)); } selectedProjects = prj.toArray(new ProjectRecord[prj.size()]); } else { monitor.worked(60); } monitor.done(); } }); } catch (InvocationTargetException e) { MercurialEclipsePlugin.logError(e.getMessage(), e.getCause()); } catch (InterruptedException e) { // Nothing to do if the user interrupts. } projectsList.refresh(false); validateSelectedProjects(); defaultEnableProjects(); projectsList.setExpandedElements(selectedProjects); projectsList.refresh(true); } /** * Collect the list of .project files that are under directory into files. * * @param files * @param directory * @param directoriesVisited * Set of canonical paths of directories, used as recursion guard * @param monitor * The monitor to report to * @return boolean <code>true</code> if the operation was completed. */ private boolean collectProjectFilesFromDirectory(Collection<File> files, File directory, Set<String> directoriesVisited, IProgressMonitor monitor, boolean foundPotentialProject) { if (monitor.isCanceled() || ".hg".equals(directory.getName())) { return false; } monitor.subTask("Checking: " + directory.getPath()); File[] contents = directory.listFiles(); if (contents == null) { return false; } // Initialize recursion guard for recursive symbolic links if (directoriesVisited == null) { directoriesVisited = new HashSet<String>(); try { directoriesVisited.add(directory.getCanonicalPath()); } catch (IOException exception) { StatusManager.getManager().handle(MercurialEclipsePlugin .createStatus(exception.getLocalizedMessage(), IStatus.ERROR, IStatus.ERROR, exception)); } } // first look for project description files final String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME; for (int i = 0; i < contents.length; i++) { File file = contents[i]; if (file.isFile() && file.getName().equals(dotProject)) { files.add(file); // don't search sub-directories since we can't have nested // projects return true; } } if (foundPotentialProject) { return true; } File mavenProjectFile = null; for (int i = 0; i < contents.length; i++) { File file = contents[i]; if (file.isFile() && file.getName().equals("pom.xml")) { mavenProjectFile = file; } } // no project description found, so recurse into sub-directories int numberOfProjects = files.size(); for (int i = 0; i < contents.length; i++) { if (contents[i].isDirectory()) { if (!contents[i].getName().equals(METADATA_FOLDER)) { try { String canonicalPath = contents[i].getCanonicalPath(); if (!directoriesVisited.add(canonicalPath)) { // already been here --> do not recurse continue; } } catch (IOException exception) { StatusManager.getManager().handle(MercurialEclipsePlugin.createStatus( exception.getLocalizedMessage(), IStatus.ERROR, IStatus.ERROR, exception)); } collectProjectFilesFromDirectory(files, contents[i], directoriesVisited, monitor, mavenProjectFile != null); } } } if (files.size() == numberOfProjects && mavenProjectFile != null) { files.add(mavenProjectFile); } return true; } /** * Create the selected projects * * @return boolean <code>true</code> if all project creations were * successful. */ public boolean createProjects() { saveWidgetValues(); final Object[] selected = projectsList.getCheckedElements(); createdProjects = new ArrayList<IProject>(); WorkspaceModifyOperation op = new WorkspaceModifyOperation() { @Override protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { monitor.beginTask("", selected.length); //$NON-NLS-1$ if (monitor.isCanceled()) { throw new OperationCanceledException(); } for (int i = 0; i < selected.length; i++) { try { createExistingProject((ProjectRecord) selected[i], new SubProgressMonitor(monitor, 1)); } catch (InvocationTargetException ite) { MercurialEclipsePlugin.showError(ite.getCause()); } } } finally { monitor.done(); } } }; // run the new project creation operation try { getContainer().run(true, true, op); } catch (InterruptedException e) { return false; } catch (InvocationTargetException e) { // one of the steps resulted in a core exception Throwable t = e.getTargetException(); String message = "Creation Problems"; IStatus status; if (t instanceof CoreException) { status = ((CoreException) t).getStatus(); } else { status = MercurialEclipsePlugin.createStatus(message, ERROR, IStatus.ERROR, t); } MercurialEclipsePlugin.logError(t); ErrorDialog.openError(getShell(), message, null, status); return false; } // Adds the projects to the working sets addToWorkingSets(); return true; } private void addToWorkingSets() { IWorkingSet[] selectedWorkingSets = workingSetGroup.getSelectedWorkingSets(); if (selectedWorkingSets == null || selectedWorkingSets.length == 0) { return; // no Working set is selected } IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); for (Iterator<IProject> i = createdProjects.iterator(); i.hasNext();) { IProject project = i.next(); workingSetManager.addToWorkingSets(project, selectedWorkingSets); } } /** * Create the project described in record. If it is successful return true. * * @param record * @return boolean <code>true</code> if successful * @throws InterruptedException */ private boolean createExistingProject(final ProjectRecord record, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { String projectName = record.getProjectName(); final IWorkspace workspace = ResourcesPlugin.getWorkspace(); final IProject project = workspace.getRoot().getProject(projectName); createdProjects.add(project); // See issue 10412: in case the clone is inside the workspace AND the clone directory name doesn't match // the selected project name, we have to rename cloned directory, otherwise // Eclipse will create a new EMPTY project if (record.description.getLocationURI() == null && !projectName.equals(record.getDataDir().getName())) { File newRoot = new File(record.getDataDir().getParentFile(), projectName); boolean caseDiffers = false; try { caseDiffers = newRoot.getCanonicalFile().getName().equals(record.getDataDir().getName()); } catch (IOException e) { } if (!newRoot.exists() || caseDiffers) { // we CAN use renameTo here because src and dest folders are on same file system // renameTo does NOT work on different file systems boolean renamed = record.getDataDir().renameTo(newRoot); if (!renamed) { MercurialEclipsePlugin .logError(new IllegalStateException("Couldn't rename hgroot to project dir")); return false; } } else { MercurialEclipsePlugin .logError(new IllegalStateException("New project data directory doesn't exist")); return false; } } record.description.setName(projectName); try { monitor.beginTask("Creating Projects", 100); project.create(record.description, new SubProgressMonitor(monitor, 30)); project.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 70)); } catch (CoreException e) { throw new InvocationTargetException(e); } finally { monitor.done(); } try { registerWithTeamProvider(project, monitor); } catch (CoreException e) { try { project.delete(false, true, new SubProgressMonitor(monitor, 30)); } catch (CoreException ex) { throw new InvocationTargetException(ex); } throw new InvocationTargetException(e); } return true; } private void registerWithTeamProvider(IProject p, IProgressMonitor monitor) throws CoreException { // Register the project with Team. This will bring all the // files that we cloned into the project. monitor.subTask(Messages.getString("CloneRepoWizard.subTask.registeringProject1") + " " + p.getName() //$NON-NLS-1$ + Messages.getString("CloneRepoWizard.subTaskRegisteringProject2")); //$NON-NLS-1$ RepositoryProvider.map(p, MercurialTeamProvider.class.getName()); monitor.worked(1); IWizard wizard = getWizard(); if (!(wizard instanceof CloneRepoWizard)) { return; } IHgRepositoryLocation repo = ((CloneRepoWizard) wizard).getRepository(); // It appears good. Stash the repo location. monitor.subTask(Messages.getString("CloneRepoWizard.subTask.addingRepository.1") + " " + repo //$NON-NLS-1$ + Messages.getString("CloneRepoWizard.subTask.addingRepository.2")); //$NON-NLS-1$ if (destinationDir instanceof HgRoot) { MercurialEclipsePlugin.getRepoManager().addRepoLocation((HgRoot) destinationDir, repo); } monitor.worked(1); } /** * The <code>WizardDataTransfer</code> implementation of this * <code>IOverwriteQuery</code> method asks the user whether the existing * resource at the given path should be overwritten. * * @param pathString * @return the user's reply: one of <code>"YES"</code>, <code>"NO"</code>, * <code>"ALL"</code>, or <code>"CANCEL"</code> */ public String queryOverwrite(String pathString) { Path path = new Path(pathString); String messageString; // Break the message up if there is a file name and a directory // and there are at least 2 segments. if (path.getFileExtension() == null || path.segmentCount() < 2) { messageString = "'" + pathString + "' already exists. Would you like to overwrite it?"; } else { messageString = "Overwrite '" + path.lastSegment() + "' in folder '" + path.removeLastSegments(1).toOSString() + "'?"; } final MessageDialog dialog = new MessageDialog(getContainer().getShell(), "Question", null, messageString, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.YES_TO_ALL_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.NO_TO_ALL_LABEL, IDialogConstants.CANCEL_LABEL }, 0) { @Override protected int getShellStyle() { // TODO add "| SWT.SHEET" flag as soon as we drop Eclipse 3.4 support return super.getShellStyle()/* | SWT.SHEET*/; } }; String[] response = new String[] { YES, ALL, NO, NO_ALL, CANCEL }; // run in syncExec because callback is from an operation, // which is probably not running in the UI thread. getControl().getDisplay().syncExec(new Runnable() { public void run() { dialog.open(); } }); return dialog.getReturnCode() < 0 ? CANCEL : response[dialog.getReturnCode()]; } /** * Method used for test suite. * * @return CheckboxTreeViewer the viewer containing all the projects found */ public CheckboxTreeViewer getProjectsList() { return projectsList; } /** * Retrieve all the projects in the current workspace. * * @return IProject[] array of IProject in the current workspace */ private IProject[] getProjectsInWorkspace() { if (wsProjects == null) { wsProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); } return wsProjects; } /** * Get the array of project records that can be imported from the * source workspace or archive, selected by the user. * * @return ProjectRecord[] array of projects that can be imported into the * workspace */ private ProjectRecord[] getSubProjectRecords() { List<ProjectRecord> projectRecords = new ArrayList<ProjectRecord>(); for (int i = 1; i < selectedProjects.length; i++) { projectRecords.add(selectedProjects[i]); } return projectRecords.toArray(new ProjectRecord[projectRecords.size()]); } /** * Determine if the project with the given name is in the current workspace. * * @param projectName * String the project name to check * @return boolean true if the project with the given name is in this * workspace */ private boolean isProjectInWorkspace(String projectName) { if (projectName == null) { return false; } IProject[] workspaceProjects = getProjectsInWorkspace(); for (int i = 0; i < workspaceProjects.length; i++) { if (projectName.equalsIgnoreCase(workspaceProjects[i].getName())) { return true; } } return false; } /** * Use the dialog store to restore widget values to the values that they * held last time this wizard was used to completion, or alternatively, * if an initial path is specified, use it to select values. * * Method declared public only for use of tests. */ public void restoreWidgetValues() { // First, check to see if we have resore settings, and // take care of the checkbox // IDialogSettings settings = getDialogSettings(); } /** * Since Finish was pressed, write widget values to the dialog store so that * they will persist into the next invocation of this wizard page. * * Method declared public only for use of tests. */ public void saveWidgetValues() { // IDialogSettings settings = getDialogSettings(); } public void setInitialSelection(File destinationDirectory) { destinationDir = destinationDirectory; if (destinationDirText != null) { destinationDirText.setText(destinationDir.getAbsolutePath()); } updateProjectsList(destinationDir.getAbsolutePath()); } private void enableProject(ProjectRecord record) { if (!record.hasConflicts) { projectsList.setChecked(record, true); if (!ENABLE_NESTED_CHECK) { if (record == selectedProjects[0]) { disableAllSubProjects(); } else { disableMainProject(); } } } else { projectsList.setChecked(record, false); } fixFinishState(); } private void disableProject(ProjectRecord record) { projectsList.setChecked(record, false); fixFinishState(); } private void enableAllSubProjects() { for (int i = 1; i < selectedProjects.length; i++) { enableProject(selectedProjects[i]); } } private void disableAllSubProjects() { for (int i = 1; i < selectedProjects.length; i++) { disableProject(selectedProjects[i]); } } private void enableMainProject() { if (isMainProjectActive()) { enableProject(selectedProjects[0]); } } private void disableMainProject() { disableProject(selectedProjects[0]); } private void enableAllProjects() { if (ENABLE_NESTED_CHECK) { enableMainProject(); } enableAllSubProjects(); } private void disableAllProjects() { disableMainProject(); disableAllSubProjects(); } private void defaultEnableProjects() { if (ENABLE_NESTED_CHECK) { enableAllProjects(); } else { if (selectedProjects.length > 1) { enableAllSubProjects(); } else if (selectedProjects.length == 1) { enableMainProject(); } } } private void validateProject(ProjectRecord record, boolean value) { if (!value) { record.hasConflicts = true; projectsList.setGrayed(record, true); } else { record.hasConflicts = false; projectsList.setGrayed(record, false); } } /** * If a project with the * same name exists in both the source workspace and the current workspace, * then the hasConflicts flag would be set on that project record. */ private void validateSelectedProjects() { boolean hasConflict = false; for (int i = 0; i < selectedProjects.length; i++) { ProjectRecord record = selectedProjects[i]; boolean v = isProjectInWorkspace(record.getProjectName()); validateProject(record, !v); hasConflict = hasConflict && v; } if (!hasConflict) { setMessage(null, WARNING); setDescription(DESCRIPTION); } else { setMessage("Some projects cannot be imported because they already exist in the workspace. " + "Double click on project to change project name.", WARNING); } if (selectedProjects.length == 0) { setMessage("No projects are selected to import", WARNING); } } private class ProjectNameScope { private final Set<String> names = new HashSet<String>(); public String getAvailableName(String name, String fallbackName) { if (!isAvailable(name)) { if (isAvailable(fallbackName)) { name = fallbackName; } else { for (int i = 1; i <= 50; i++) { String cur = name + i; if (isAvailable(cur)) { name = cur; break; } } } } names.add(name); return name; } private boolean isAvailable(String name) { return name != null && !names.contains(name) && !isProjectInWorkspace(name); } } }