### Eclipse Workspace Patch 1.0 #P org.eclipse.core.resources Index: src/org/eclipse/core/resources/ResourcesPlugin.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/resources/ResourcesPlugin.java,v retrieving revision 1.50 diff -u -r1.50 ResourcesPlugin.java --- src/org/eclipse/core/resources/ResourcesPlugin.java 7 Apr 2008 08:55:44 -0000 1.50 +++ src/org/eclipse/core/resources/ResourcesPlugin.java 24 Mar 2009 21:22:19 -0000 @@ -96,6 +96,13 @@ public static final String PT_MODEL_PROVIDERS = "modelProviders"; //$NON-NLS-1$ /** + * Simple identifier constant (value "migrationHelpers") + * for the migration helpers extension point. + * + */ + public static final String PT_MIGRATION_HELPERS = "migrationHelpers"; //$NON-NLS-1$ + + /** * Constant identifying the job family identifier for the background autobuild job. * * @see IJobManager#join(Object, IProgressMonitor) @@ -256,6 +263,8 @@ */ public static final String PREF_AUTO_REFRESH = "refresh.enabled"; //$NON-NLS-1$ + + /** * The single instance of this plug-in runtime class. */ Index: plugin.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/plugin.properties,v retrieving revision 1.21 diff -u -r1.21 plugin.properties --- plugin.properties 3 Jun 2008 12:34:52 -0000 1.21 +++ plugin.properties 24 Mar 2009 21:22:19 -0000 @@ -19,6 +19,7 @@ preferencesContentTypeName = Preferences refreshProvidersName=Refresh Providers modelProviders=Model Providers +migrationHelpers=Migration Helpers preferencesExtPtName=Resource Preferences resourceModelName=File System Resources Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/plugin.xml,v retrieving revision 1.80 diff -u -r1.80 plugin.xml --- plugin.xml 8 Jan 2009 10:48:16 -0000 1.80 +++ plugin.xml 24 Mar 2009 21:22:19 -0000 @@ -10,6 +10,7 @@ + @@ -188,5 +189,23 @@ properties="projectPersistentProperty" id="org.eclipse.core.resources.mappingPropertyTester"/> + + + + + + + + + + + + Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/META-INF/MANIFEST.MF,v retrieving revision 1.25 diff -u -r1.25 MANIFEST.MF --- META-INF/MANIFEST.MF 8 Jan 2009 10:48:16 -0000 1.25 +++ META-INF/MANIFEST.MF 24 Mar 2009 21:22:19 -0000 @@ -15,11 +15,13 @@ org.eclipse.core.internal.refresh;x-internal:=true, org.eclipse.core.internal.resources;x-internal:=true, org.eclipse.core.internal.resources.mapping;x-internal:=true, + org.eclipse.core.internal.resources.projectmigration, org.eclipse.core.internal.resources.refresh.win32;x-internal:=true, org.eclipse.core.internal.utils;x-internal:=true, org.eclipse.core.internal.watson;x-internal:=true, org.eclipse.core.resources, org.eclipse.core.resources.mapping, + org.eclipse.core.resources.projectmigration, org.eclipse.core.resources.refresh, org.eclipse.core.resources.team Require-Bundle: org.eclipse.ant.core;bundle-version="[3.1.0,4.0.0)";resolution:=optional, Index: schema/migrationHelpers.exsd =================================================================== RCS file: schema/migrationHelpers.exsd diff -N schema/migrationHelpers.exsd --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ schema/migrationHelpers.exsd 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,138 @@ + + + + + + + + + This extension point allows contributors to assist with Project Migrations. Contributors get two chances to help. + +The first is on the export of the Project information. Contributors can create files that should be included in the zip file that is copied to the new directory. Contributors can also identify files that should be copied from the source directory to the new directory. At this stage, contributors are only called for projects with a nature that matches one in the list of natures that the contributor knows about. + +The second opportunity is when the Project Migration is actually happening. The contributors are called for each file that is copied from the original source directory. The contributor can change the copied file in order to reflect the new project name or other changes. + +A contributor makes a class that extends ProjectMigrationHelper. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + These elements specify the "natures" that this extension knows about. Multiple natures can be specified. + + + + + + + Identifies the project nature. Projects with the specified nature can be helped by this particular migrationHelper. + + + + + + + + + + + + This must be a class that extends org.eclipse.core.resources.projectmigration.ProjectMigrationHelper. + + + + + + + + + + + + + + + 3.5 + + + + + + + + + For CDT, the provided class provides the following functions: + +createExportFiles(): This function exports the PDOM (much like the Team Shared Index) and identifies the ".cproject" file to be copied at the time of the migration. + +migrateFile(): This function changes the .cproject file so that instances of the old project name are changed to the new name. A possible improvement is to use the old and new linked prefixes to make changes to the include paths specified. + +The removeExportFiles() is not provide because the default implementation which just removes all files like the exported PDOM is the desired behavior. + + + + + + + + + + + When the Project Migration information is being exported, the function "createExportFiles" is called. This allows the contributor to create temporary files to be included in the migration zip file. (these files will be deleted later on by a call to "removeExportFiles". For each file created, the contributor should call "addExportZipFile". The contributor can override removeExportFiles if the files added via addExportZipFile should not all be deleted. + +In addition to creating temporary files to be included in the migration zip file, the contributor can also indicate files to be copied from the project source directory to the migration destination directory. These files should be in the project directory. (i.e. not a file in a sub-directory.) This list of files is added through calls to "addFileToMigrate". + +When the Project Migration is being performed, the function "migrateFile" is called so the contributor has a chance to change the destination file. + + + + + + + + + An example of this extension is included with CDT. + + + + + Index: src/org/eclipse/core/internal/resources/projectmigration/SFSUtilities.java =================================================================== RCS file: src/org/eclipse/core/internal/resources/projectmigration/SFSUtilities.java diff -N src/org/eclipse/core/internal/resources/projectmigration/SFSUtilities.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/resources/projectmigration/SFSUtilities.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 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: + * Wind River Systems Inc.- initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.resources.projectmigration; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import org.eclipse.core.internal.resources.projectmigration.Messages; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; + +/** + * + */ +public class SFSUtilities { + + public static void exportRefreshInfo( IProjectDescription desc, File tmpfile, IProgressMonitor monitor) { + URI projectURI = desc.getLocationURI(); + SnapInfoStore refreshInfo = new SnapInfoStore(projectURI.getPath(), + tmpfile); + monitor.subTask(Messages.getString("SFSUtilities.0")); //$NON-NLS-1$ + refreshInfo.write(new SubProgressMonitor(monitor, 100)); + monitor.done(); + } + + public static void startUsingRefreshInfo( IProjectDescription description, IPath destPath, String snap_name, int numberOfLocals) { + URI uri = description.getLocationURI(); + URI projURI = null; + try { + projURI = new URI(SFSFileSystem.SCHEME, uri.getAuthority(), "/", //$NON-NLS-1$ + destPath.toString(), snap_name); + } catch (URISyntaxException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, "uri", //$NON-NLS-1$ + e)); + return; + } + SFSFileSystem.setRootPath(destPath.toString(), numberOfLocals); + description.setLocationURI(projURI); + } + public static void addRootLocalFile( String fileName ) { + SFSFileSystem.setRootLocalFile( fileName ); + } + + public static void stopUsingRefreshInfo( ) { + SFSFileSystem.stopUsingRefreshInfo(); + } +} Index: src/org/eclipse/core/resources/projectmigration/ProjectMigration.java =================================================================== RCS file: src/org/eclipse/core/resources/projectmigration/ProjectMigration.java diff -N src/org/eclipse/core/resources/projectmigration/ProjectMigration.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/resources/projectmigration/ProjectMigration.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,475 @@ +/******************************************************************************* + * Copyright (c) 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: + * Wind River Systems, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.resources.projectmigration; + +import org.eclipse.core.runtime.*; + +import org.eclipse.core.runtime.IExecutableExtension; + +import org.eclipse.core.internal.resources.projectmigration.Messages; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; +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.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.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +//import org.eclipse.core.internal.resources.projectmigration.PlatformProjectMigrationHelper; +import org.eclipse.core.internal.resources.projectmigration.SFSUtilities; + +/** + * An operation which does the actual work of migrating a project from one + * directory to another. + *

+ * This class may be instantiated; it is not intended to be subclassed. + *

+ */ +public class ProjectMigration { + + public static final String SNAP_NAME = ".projdir.snap"; //$NON-NLS-1$ + public static final String MIGRATION_ZIP_NAME = ".projmig.zip"; //$NON-NLS-1$ + + private IPath sourcePath; + + private IPath destinationPath; + + private String projectName; + private String newProjectName; + + private String oldLinkedPathPrefix; + + private String newLinkedPathPrefix; + + /** + * Specifies a project migration that performs a "trusted import" of the + * specified project from the source directory to the destination directory. + * This means that the file refresh information and other files from the source + * project are to be imported and trusted, i.e., not verified. + *

+ * The sourcePath parameter represents the directory containing + * the project to import. + *

+ * + * @param destinationPath + * full path of destination directory + * @param sourcePath + * full path of source directory, containing a project + * @param newName + * new name of project (empty if no rename) + */ + public ProjectMigration( IPath sourcePath, String newName, IPath destinationPath){ + super(); + this.projectName = "uninitialized_project_name"; //$NON-NLS-1$ + + this.sourcePath = sourcePath; + this.destinationPath = destinationPath; + this.newProjectName = newName; + this.oldLinkedPathPrefix = ""; //$NON-NLS-1$ + this.newLinkedPathPrefix = ""; //$NON-NLS-1$ + } + + /** + * Sets the linked directory path prefix. + * + * @param oldLinkedPathPrefix + * linked to the old directory path prefix + * @param newLinkedPathPrefix + * linked to the new directory path prefix + */ + public void setLinkedPathPrefix(String oldLinkedPathPrefix, String newLinkedPathPrefix) { + this.oldLinkedPathPrefix = oldLinkedPathPrefix; + this.newLinkedPathPrefix = newLinkedPathPrefix; + } + + + /* + * Method declared on WorkbenchModifyOperation. Imports the specified + * project from the file system. + * + * @param progressMonitor IProgressMonitor object + */ + public void execute(IProgressMonitor progressMonitor) throws Exception { + /* TODO: remove this? + * Check the cdt debug activity settings. If on, print a message to + * stdout announcing that the Project migration is starting. This makes + * timing the migration easier. Please note that the hard-coded + * references to the plugin and activity names is a bit of a kludge. It + * would not be needed if the project migration API were actually part + * of CDT instead of in a separate plugin. + */ + String option = "org.eclipse.cdt.core/debug/indexer/activity"; //$NON-NLS-1$ + String trace = Platform.getDebugOption(option); + boolean internallyActivated = Boolean.getBoolean(option); + boolean showActivity = internallyActivated || (trace != null && trace.equalsIgnoreCase("true")); //$NON-NLS-1$ + if (showActivity == true) { + System.out.println(Messages.getString("ProjectMigration.0")); //$NON-NLS-1$ + } + IProgressMonitor monitor = progressMonitor; + if( monitor == null ) { + monitor = new NullProgressMonitor(); + } + monitor.beginTask("", 100 ); //$NON-NLS-1$ + if (sourcePath.equals(destinationPath)) { + throw new Exception(Messages.getString("ProjectMigration.1")); //$NON-NLS-1$ + } + try { + { + IPath path = sourcePath.append(IProjectDescription.DESCRIPTION_FILE_NAME); + final IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IProjectDescription description = workspace.loadProjectDescription(path); + this.projectName = description.getName(); + } + extractMigrationFiles(sourcePath, destinationPath); + + File[] projectFiles = getProjectFiles(sourcePath); + if (projectFiles.length == 0) { + throw new Exception(Messages.getString("ProjectMigration.2")); //$NON-NLS-1$ + } + int i = 0; + + for (i = 0; i < projectFiles.length; i++) { + File file = projectFiles[i]; + if (file != null) { + if (!copyRecursively(file, destinationPath, new SubProgressMonitor( monitor, 20/projectFiles.length))) { + throw new Exception(Messages.getString("ProjectMigration.4")); //$NON-NLS-1$ + } + } + } + + IPath path = destinationPath; + + /* + * Let the project migration helpers have a chance at changing the copied files. + */ + changeCopiedFiles( projectFiles, new SubProgressMonitor( monitor, 20 ) ); + +// PlatformProjectMigrationHelper projFile = new PlatformProjectMigrationHelper(path, projectFiles, newProjectName, oldLinkedPathPrefix, newLinkedPathPrefix); + +// projFile.performProjectRenaming(new SubProgressMonitor(monitor,20)); + + path = destinationPath.append(IProjectDescription.DESCRIPTION_FILE_NAME); + + final IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IProjectDescription description = workspace.loadProjectDescription(path); + String projName = description.getName(); + final IProject project = workspace.getRoot().getProject(projName); + + File importFile = destinationPath.append(ProjectMigration.SNAP_NAME).toFile(); + if (importFile.exists()) { + SFSUtilities.startUsingRefreshInfo(description, destinationPath, ProjectMigration.SNAP_NAME, projectFiles.length); + for( i = 0; i < projectFiles.length; i++ ) { + SFSUtilities.addRootLocalFile(projectFiles[i].getName()); + } + } + + project.create(description, new SubProgressMonitor( monitor, 10 )); + + // open the project and perform the refresh before returning + project.open(IResource.NONE, new SubProgressMonitor( monitor, 40 ) ); + } + finally { + // now turn off the use of the snapshot file, if active + SFSUtilities.stopUsingRefreshInfo(); + } + monitor.done(); + } + + private void changeCopiedFiles(File[] projectFiles, IProgressMonitor monitor) { + IExecutableExtension[] extensions = getMigrationHelpers(); + if( extensions.length == 0 ) { + monitor.done(); + return; + } + for( int i = 0; i < projectFiles.length; i++ ) { + + /* + * Ask the helpers to migrate files that are copied. + */ + + for( int j = 0; j < extensions.length; j ++ ) { + if (extensions[j] instanceof ProjectMigrationHelper) { + ProjectMigrationHelper helper = (ProjectMigrationHelper) extensions[j]; + IPath filePath = destinationPath.append( projectFiles[i].getName()); + helper.migrateFile( filePath, projectName, newProjectName, oldLinkedPathPrefix, newLinkedPathPrefix); + } + } + monitor.worked(1); + } + } + + /* + * Get the set of migration helpers. We don't match on the natures since no + * projects are actually open. Instead, the migration helper must "know" which + * files it can help migrate. + */ + private IExecutableExtension[] getMigrationHelpers() { + List helpers = new ArrayList(); + + try { + IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_MIGRATION_HELPERS); + if (extension != null) { + IExtension[] extensions = extension.getExtensions(); + for (int i = 0; i < extensions.length; i++ ) { + IExtension extension2 = extensions[i]; + IConfigurationElement[] configElements = extension2.getConfigurationElements(); + for ( int j = 0; j < configElements.length; j ++ ) { + IConfigurationElement configElement = configElements[j]; + if( configElement.getAttribute( "class" ) != null ) { //$NON-NLS-1$ + helpers.add( configElement.createExecutableExtension("class")); //$NON-NLS-1$ + } + } + } + } + } catch (CoreException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status( IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, Messages.getString("ExportProjectMigrationInfo.4"), e)); //$NON-NLS-1$ + } + + return (IExecutableExtension[]) helpers.toArray(new IExecutableExtension[0]); + + } + + private void readEntry(ZipFile zip, ZipEntry entry, File tmpFile) + throws IOException { + InputStream stream = zip.getInputStream(entry); + OutputStream outEntry = new FileOutputStream(tmpFile); + try { + byte[] buffer = new byte[2048]; + int read; + while ((read = stream.read(buffer)) >= 0) { + outEntry.write(buffer, 0, read); + } + } finally { + close(outEntry); + } + } + + private void close(OutputStream out) { + try { + if (out != null) { + out.close(); + } + } catch (IOException e) { + ResourcesPlugin.getPlugin().getLog().log( new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.2"), e)); //$NON-NLS-1$ + + } + } + + + + /** + * Copies the specified file system object recursively into the destination + * If the import fails, adds a status object to the list to be returned by + * getStatus. + * + * @param file + * the file system object to be imported + * @exception OperationCanceledException + * if canceled + */ + private boolean copyRecursively(File file, IPath destPath, IProgressMonitor monitor) { + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + if (!file.isDirectory()) { + return copyFile(file, destPath, monitor); + } + + IPath folderPath = destPath.addTrailingSeparator(); + folderPath = folderPath.append(file.getName()); + boolean success = new File(folderPath.toOSString()).mkdir(); + if (!success) { + monitor.done(); + return false; + } + File[] contents = file.listFiles(); + monitor.beginTask("", contents.length); //$NON-NLS-1$ + for (int i = 0; i < contents.length; i++) { + if (!copyRecursively(contents[i], folderPath, new SubProgressMonitor( monitor, 1 ) )) { + monitor.done(); + return false; + } + } + monitor.done(); + return true; + } + + /** + * Copies the specified file system object into the destination. If the copy + * fails, returns false. + */ + private boolean copyFile(File file, IPath dPath, IProgressMonitor monitor) { + + String filePath = file.getAbsolutePath(); + monitor.subTask(filePath); + + // assume that the source and target are not the same + try { + FileInputStream from = null; + try { + from = new FileInputStream(file); + } catch (FileNotFoundException e) { + // file was not found. null case is handled. + } + if (from == null) { + monitor.done(); + return false; + } + IPath destPath = dPath.addTrailingSeparator(); + destPath = destPath.append(file.getName()); + FileOutputStream to = null; + try { + to = new FileOutputStream(destPath.toString()); + } catch (FileNotFoundException e) { + from.close(); + monitor.done(); + return false; + } + try { + byte[] buffer = new byte[4096]; + int bytesRead; + + while ((bytesRead = from.read(buffer)) != -1) + to.write(buffer, 0, bytesRead); // write + } finally { + try { + from.close(); + } catch (IOException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.6"), e)); //$NON-NLS-1$ + + } + + try { + to.close(); + } catch (IOException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.7"), e)); //$NON-NLS-1$ + + } + } + monitor.done(); + return true; + } catch (IOException e) { + monitor.done(); + return false; + } + } + + /** + * Get the list of files that need to be copied from this directory. This + * includes any 0-length entries in the zip file. The 0-length + * entries are used to capture the names of files that the migration helper + * extensions wanted to have copied. + */ + private File[] getProjectFiles(IPath importSourcePath) { + + /* + * Look for the Migration zip file + */ + File zipFile = importSourcePath.append(ProjectMigration.MIGRATION_ZIP_NAME).toFile(); + if( !zipFile.exists() ) { + return new File[0]; + } + + /* + * Open the zip file and get the list of names for the entries that are 0 length. This + * should be a list of files to copy. Verify that the names are in the contents. + */ + List files = new ArrayList(); + try { + ZipFile zip = new ZipFile(zipFile); + Enumeration zipEntriesList = zip.entries(); + try { + while (true) { + ZipEntry entry; + entry = (ZipEntry) zipEntriesList.nextElement(); + if (entry.getSize() == 0) { + File entryFile = importSourcePath.append(entry.getName()).toFile(); + if( entryFile.exists() ) { + files.add( entryFile ); + } + } + } + } catch (NoSuchElementException e) { + // done with all entries + } finally { + zip.close(); + } + } catch (ZipException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.8"), e)); //$NON-NLS-1$ + } catch (IOException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.9"), e)); //$NON-NLS-1$ + + } + + return (File[]) files.toArray(new File[0]); + } + /** + * Extract all non-zero length files from the zip file into the destination directory. + */ + private void extractMigrationFiles(IPath importSourcePath, IPath dPath) { + + /* + * Look for the Migration zip file + */ + File zipFile = importSourcePath.append(ProjectMigration.MIGRATION_ZIP_NAME).toFile(); + if( !zipFile.exists() ) { + return; + } + + try { + ZipFile zip = new ZipFile(zipFile); + Enumeration zipEntriesList = zip.entries(); + try { + while (true) { + ZipEntry entry; + entry = (ZipEntry) zipEntriesList.nextElement(); + if (entry.getSize() != 0 /*&& entry.getName().equals(ProjectMigration.SNAP_NAME)*/) { + File tmpFile = dPath.append(entry.getName()).toFile(); + readEntry( zip, entry, tmpFile); + } + } + } catch (NoSuchElementException e) { + // done with all entries + } finally { + zip.close(); + } + } catch (ZipException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.8"), e)); //$NON-NLS-1$ + } catch (IOException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.9"), e)); //$NON-NLS-1$ + + } + + return ; + } + + +} Index: src/org/eclipse/core/resources/projectmigration/ProjectMigrationHelper.java =================================================================== RCS file: src/org/eclipse/core/resources/projectmigration/ProjectMigrationHelper.java diff -N src/org/eclipse/core/resources/projectmigration/ProjectMigrationHelper.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/resources/projectmigration/ProjectMigrationHelper.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,262 @@ +/******************************************************************************* + * Copyright (c) 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 + *******************************************************************************/ +package org.eclipse.core.resources.projectmigration; + +import java.io.FileInputStream; +import java.io.FileOutputStream; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * This is the base class for ProjectMigration Extensions. + * The extension has two parts to contribute: + * + * 1. At the time of Export, the extension can: + * - create files that will be included in the zip file + * created as the output of the export. + * - specify files that should be copied from the source + * project directory to the new project directory. + * When the export is called, the createExportFiles() is called. + * This function can create files as needed and then make calls to + * addExportZipFile() and addFilesToMigrate() to specify files to + * include in the zip file and files to be copied respectively. + * + * After the zip file is created, a call is made to removeExportFiles() + * to remove the files that were added to the zip file. The assumption is + * that they were all temporary files. If this assumption is not true, then + * override the removeExportFiles() and do your own thing. + * + * At the time of the export, the extension only comes into play if the + * "nature" specified with the extension matches one of the natures in the project. + * + * 2. At the time of the migration, the extension can offer assistance with changing + * any files that are copied over from the source project to the destination project. + * This is done through calls to migrateFile(). This function is called for each file. + * The extension can change the contents as needed. Typically, the project name is + * changed so references to the old name must be changed to the new name. + * + * At the time of the migration, all extensions are called, regardless of the nature. + * The extension will need to look at the name of the file and if the file is not + * special to the extension, then it should not do anything to the file. + */ +public class ProjectMigrationHelper implements IExecutableExtension { + + /* + * This is the project that this instance is for. This field is only + * populated for the export operation. It is not populated at the time + * of the migration. + */ + private IProject fProject; + + /* + * This local class contains the file and entry name for a file that should be + * added to the zip file. + */ + public class ExportZipFileEntryInfo { + private File fFile; + private String fName; + public ExportZipFileEntryInfo( File file, String name ) { + fFile = file; + fName = name; + } + public File getFile() { + return fFile; + } + public String getName() { + return fName; + } + } + + /* + * This is the list of files to be added to the zip file. Each entry + * is an ExportZipFileEntryInfo object. + */ + public List fExportZipFiles = new ArrayList(); + + /* + * This is the list of files to be copied at the time of the migration. + * Each entry is a String. You can really only copy files or directories that are in + * the root of the project directory. + */ + private List fFilesToMigrate = new ArrayList(); + + /* + * Public Methods + */ + + /* + * Plain constructor. Extensions must have one of these. + */ + public ProjectMigrationHelper() { + return; + } + + + /** + * This function should create any files that should be included in + * the zip file representing the exported migration information. + * + * The function should create the files and make a call to addExportZipFile() + * for each file created. + * + * Files that should be copied at the time of the migration (but + * not included in the zip file) should be added through calls to addFileToMigrate() + * + * @param monitor - progress monitor for this function. + * @throws CoreException + */ + public void createExportFiles(IProgressMonitor monitor) throws CoreException { + /* + * This function should be in the sub-class if there really are files + * that need to be copied and migrated. + */ + } + + /* + * This function removes files created by createExportFiles(). + * It is assumed that all files created are temporary files and should be + * deleted. If this is the case, then this default implementation is sufficient. + * If this is not the case, then the extension should override this function + * and determine the proper disposal of the files created in createExportFiles. + */ + public void removeExportFiles() { + for( int i = 0; i < fExportZipFiles.size(); i++) { + ExportZipFileEntryInfo exportFile = (ExportZipFileEntryInfo) fExportZipFiles.get(i); + File file = exportFile.getFile(); + file.delete(); + } + fExportZipFiles = null; + } + /** + * This function is called for each file that is copied from the source project directory. The Extension + * has an opportunity to change the contents of the file. + * + * The function is called after the file has been copied. The extension should only change the destination + * file. (filePath) + + * @param filePath - path of the copied file + * @param oldname - name of the original project + * @param newname - name of the migrated project + * @param fromLinked - A prefix for linked folders or other paths + * @param toLinked - What the fromLinked prefix should be changed to + * @return true if file is modified, else return false. + */ + public boolean migrateFile( IPath filePath, String oldname, String newname, String fromLinked, String toLinked ) { + return false; + } + + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object) + * + * + * Override this function if you have added other extension elements and want to do something with that data. + */ + + /** + * @throws CoreException + */ + public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { + /* + * This function will get any properties and values associated with the extension point. + * The sub-class should have its own version if it wants to save the properties and do something + * with them. + */ + + } + + + /** + * Set the project that this extension is associated with. + * This will be null during the actual migration itself since + * neither the source nor the destination projects are actually + * open. + * + * @param project + */ + public final void setProject( IProject project ) { + fProject = project; + } + + /* + * Return the project (could be null) associated with this extension. + */ + public final IProject getProject( ) { + return fProject; + } + + + public final void addExportZipFile( File file, String entryName ) { + ExportZipFileEntryInfo info = new ExportZipFileEntryInfo( file, entryName ); + fExportZipFiles.add( info ); + } + + + + public final List getExportZipFiles() { + return fExportZipFiles; + } + + public final List getFilesToMigrate() { + return fFilesToMigrate; + } + + public void addFileToMigrate(String name) { + fFilesToMigrate.add(name); + } + + /* + * Utility Functions + */ + + /** + * Read a file into a String class. + * + * @param filepath + * path to the file to read *@return file contents as a string + */ + public String readFileIntoString(String filepath) throws Exception { + FileInputStream fis = new FileInputStream(filepath); + int x = fis.available(); + byte b[] = new byte[x]; + + fis.read(b); + fis.close(); + + return new String(b); + } + + /** + * Write the string to a file. + * + * @param filepath + * path to the file to write to + * @param data + * string containing the data to write + */ + public void writeStringIntoFile(String filepath, String data) + throws Exception { + FileOutputStream fos = new FileOutputStream(filepath); + byte b[] = data.getBytes(); + + fos.write(b); + fos.close(); + } + +} Index: src/org/eclipse/core/internal/resources/projectmigration/SnapInfo.java =================================================================== RCS file: src/org/eclipse/core/internal/resources/projectmigration/SnapInfo.java diff -N src/org/eclipse/core/internal/resources/projectmigration/SnapInfo.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/resources/projectmigration/SnapInfo.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006, 2008 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: + * Wind River Systems, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.resources.projectmigration; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.provider.FileInfo; + +public class SnapInfo extends FileInfo { + + // same as FileInfo.ATTRIBUTE_DRECTORY which is unfortunately private + static int ATTRIBUTE_DIRECTORY = 1 << 0; + + int nextIndex; + int parentIndex; + int childIndex; + + public SnapInfo(String name) { + super(name); + nextIndex = 0; + parentIndex = 0; + childIndex = 0; + } + + public void setAttributes(int attributes) { + if ((attributes & EFS.ATTRIBUTE_READ_ONLY) != 0) { + setAttribute(EFS.ATTRIBUTE_READ_ONLY, true); + } + if ((attributes & EFS.ATTRIBUTE_EXECUTABLE) != 0) { + setAttribute(EFS.ATTRIBUTE_EXECUTABLE, true); + } + if ((attributes & EFS.ATTRIBUTE_ARCHIVE) != 0) { + setAttribute(EFS.ATTRIBUTE_ARCHIVE, true); + } + if ((attributes & EFS.ATTRIBUTE_HIDDEN) != 0) { + setAttribute(EFS.ATTRIBUTE_HIDDEN, true); + } + if ((attributes & ATTRIBUTE_DIRECTORY) != 0) { + setDirectory(true); + } + } + + //@Override + public boolean exists() { + return true; // we always act as if the file exists + } + + //@Override + public void setExists(boolean value) { + // ignore attempts to change this + } + + //@Override + public String getStringAttribute(int attribute) { + // all symbolic links are resolved in the snapshot + return null; + } + + //@Override + public void setStringAttribute(int attribute, String value) { + // ignore attempts to change this + } + + public int getNextIndex() { + return nextIndex; + } + + public void setNextIndex(int x) { + nextIndex = x; + } + + public int getParentIndex() { + return parentIndex; + } + + public void setParentIndex(int x) { + parentIndex = x; + } + + public int getChildIndex() { + return childIndex; + } + + public void setChildIndex(int x) { + childIndex = x; + } +} Index: src/org/eclipse/core/internal/resources/projectmigration/Messages.java =================================================================== RCS file: src/org/eclipse/core/internal/resources/projectmigration/Messages.java diff -N src/org/eclipse/core/internal/resources/projectmigration/Messages.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/resources/projectmigration/Messages.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 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 + *******************************************************************************/ +package org.eclipse.core.internal.resources.projectmigration; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * + */ +public class Messages { + private static final String BUNDLE_NAME = "org.eclipse.core.internal.resources.projectmigration.messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME); + + private Messages() { + /* + * no initialization needed + */ + } + + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +} Index: src/org/eclipse/core/internal/resources/projectmigration/messages.properties =================================================================== RCS file: src/org/eclipse/core/internal/resources/projectmigration/messages.properties diff -N src/org/eclipse/core/internal/resources/projectmigration/messages.properties --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/resources/projectmigration/messages.properties 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,20 @@ +ExportProjectMigrationInfo.0=Error creating temporary file +ExportProjectMigrationInfo.1=Error closing input stream +ExportProjectMigrationInfo.2=Error closing output stream +ExportProjectMigrationInfo.3=Error writing entries to zip file +ExportProjectMigrationInfo.4=Exception received trying to get extensions +ExportProjectMigrationInfo.5=Preparing Files +ExportProjectMigrationInfo.6=Storing Files + +PlatformProjectMigrationHelper.0=Exception trying to migrate file: +ProjectMigration.0=Starting Project Migration. +ProjectMigration.1=Destination same as source directory +ProjectMigration.2=No project files present +ProjectMigration.3=No files other than project files found +ProjectMigration.4=Error copying .project, etc. +ProjectMigration.5=Error closing the zip file +ProjectMigration.6=Error closing file +ProjectMigration.7=Error closing file +ProjectMigration.8=Error accessing migration Zipfile +ProjectMigration.9=I/O Error accessing migration Zipfile +SFSUtilities.0=Writing Project Migration Information Index: src/org/eclipse/core/internal/resources/projectmigration/PlatformProjectMigrationHelper.java =================================================================== RCS file: src/org/eclipse/core/internal/resources/projectmigration/PlatformProjectMigrationHelper.java diff -N src/org/eclipse/core/internal/resources/projectmigration/PlatformProjectMigrationHelper.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/resources/projectmigration/PlatformProjectMigrationHelper.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,385 @@ + +/******************************************************************************* + * Copyright (c) 2000, 2006, 2008 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: + * Wind River Systems, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.resources.projectmigration; + + + +import org.eclipse.core.runtime.Status; + +import org.eclipse.core.runtime.IStatus; + +import org.eclipse.core.runtime.CoreException; + + + +import org.eclipse.core.runtime.IProgressMonitor; + +import javax.xml.transform.OutputKeys; + +import javax.xml.transform.Transformer; + +import javax.xml.transform.TransformerFactory; + +import javax.xml.transform.stream.StreamResult; + +import javax.xml.transform.dom.DOMSource; + +import java.io.File; + + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.projectmigration.ProjectMigrationHelper; +import org.eclipse.core.resources.ResourcesPlugin; + + +import org.eclipse.core.runtime.IPath; + + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * An operation which does the actual work of renaming the project name in the + * .project file and using extension points to modify other files. + *

+ * This class may be instantiated; it is not intended to be subclassed. + *

+ */ +/* + * public class ProjectMigrationExtension extends ProjectMigrationHelper { + + + @Override + + private void checkMonitor(IProgressMonitor monitor) { + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + } + + @ Override + public boolean migrateFile( IPath filePath, String oldname, String newname, String fromLinked, String toLinked ) { + if( filePath.toFile().getName().equals(".cproject") ) { //$NON-NLS-1$ + + try { + // process the .cproject file + String data = readFileIntoString(filePath.toString()); + + String new_data = data + .replaceAll("\\b" + oldname + "\\b", newname); //$NON-NLS-1$ //$NON-NLS-2$ + if (!data.equals(new_data)) { + writeStringIntoFile(filePath.toString(), new_data); + } + } catch (Exception e) { + CCorePlugin.log( Messages.ProjectMigrationExtension_2, e ); + } + } + return true; + } +} +*/ +public class PlatformProjectMigrationHelper extends ProjectMigrationHelper { + + + public PlatformProjectMigrationHelper() { + super(); + } + /** + * @throws CoreException + */ + public void createExportFiles(IProgressMonitor monitor) throws CoreException { + monitor.beginTask("", 100); //$NON-NLS-1$ + + addFileToMigrate( IProjectDescription.DESCRIPTION_FILE_NAME ); + monitor.done(); + + } + /** + * Specifies a project rename operation. This means that the project name in + * the .project files are renamed. + */ + /* + public PlatformProjectMigrationHelper(IPath path, File[] projFiles, String newProjectName, + String oldLinkPathPrefix, String newLinkPathPrefix) { + projectPath = path; + IPath projPath = path; + + projectFiles = projFiles; + projPath = projPath.addTrailingSeparator(); + projPath = projPath.append(IProjectDescription.DESCRIPTION_FILE_NAME); + this.projectFile = projPath.toString(); + + this.newProjectName = newProjectName; + this.oldLinkPathPrefix = oldLinkPathPrefix; + this.newLinkPathPrefix = newLinkPathPrefix; + this.modified = false; + } + */ + public boolean migrateFile( IPath filePath, String oldname, String newname, String fromLinked, String toLinked ) { + if( filePath.toFile().getName().equals(IProjectDescription.DESCRIPTION_FILE_NAME) ) { + + try { + Document dom = parseProjectFile(filePath); + if ( processLinkedResources(dom, fromLinked, toLinked) == true ) { + saveProjectFile(filePath, dom); + } + // process the .project file + String data = readFileIntoString(filePath.toString()); + + String new_data = data + .replaceAll("\\b" + oldname + "\\b", newname); //$NON-NLS-1$ //$NON-NLS-2$ + if (!data.equals(new_data)) { + writeStringIntoFile(filePath.toString(), new_data); + } + } catch (Exception e) { + ResourcesPlugin.getPlugin().getLog().log( new Status( IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, Messages.getString("PlatformProjectMigrationHelper.0") + filePath.toString(), e) ); //$NON-NLS-1$ + } + } + return true; + } + + + /** + * Parse the xml project files. + * + * @return true if successful otherwise false + */ + private Document parseProjectFile(IPath filePath) throws Exception { + // get the factory + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + + // Using factory get an instance of document builder + DocumentBuilder db = dbf.newDocumentBuilder(); + + // parse using builder to get DOM representation of the XML file + return db.parse(filePath.toFile()); + + } + + /** + * Process the linked resource directories that is in the .project file. + * + * @param oldPath + * prefix to the old path + * @param newPath + * prefix to the new path + */ + private boolean processLinkedResources(Document dom, String oldPath, String newPath) { + // get the root element + + Element docEle = dom.getDocumentElement(); + boolean changed = false; + + Node last = docEle.getLastChild(); + Node curr = docEle.getFirstChild(); // get the root element + boolean found = false; + + while (curr != last) { + if (curr.getNodeName().equals("linkedResources")) { //$NON-NLS-1$ + found = true; + break; + } + curr = curr.getNextSibling(); + } + + if (!found) + return changed; + + // get the root element + NodeList listOfLinkedResources = curr.getChildNodes(); + if (listOfLinkedResources == null) + return changed; + + int totalResources = listOfLinkedResources.getLength(); + + for (int s = 0; s < totalResources; s++) { + + Node linkLinkedResourcesNode = listOfLinkedResources.item(s); + if (linkLinkedResourcesNode.getNodeType() == Node.ELEMENT_NODE) { + + Element linkLinkedResourcesElement = (Element) linkLinkedResourcesNode; + + // ------- + NodeList locationNameList = linkLinkedResourcesElement + .getElementsByTagName("location"); //$NON-NLS-1$ + if (locationNameList == null) + return changed; + + Element locationNameElement = (Element) locationNameList + .item(0); + + NodeList textFNList = locationNameElement.getChildNodes(); + String val = textFNList.item(0).getNodeValue(); + + if (val.startsWith(oldPath)) { + val = newPath + val.substring(oldPath.length()); + textFNList.item(0).setNodeValue(val); + changed = true; + } + }// end of if clause + + }// end of for loop with s var + return changed; + } + + /** + * Get the project name in the .project xml file. + * + * @return the project name + */ +/* private String getProjectName() { + + // get the root element + Element docEle = dom.getDocumentElement(); + + Node first = docEle.getFirstChild(); + Node last = docEle.getLastChild(); + Node curr = first; + + while (curr != last) { + if (curr.getNodeName().equals("name")) { //$NON-NLS-1$ + + return curr.getTextContent(); + } + curr = curr.getNextSibling(); + } + return null; + } +*/ + /** + * Save the .profile file. + * + * @return true if successful otherwise false + */ + private boolean saveProjectFile(IPath filePath, Document dom) throws Exception { + + + // Serialization through Transform. + File filename = filePath.toFile(); + + DOMSource domSource = new DOMSource(dom); + StreamResult streamResult = new StreamResult(filename); + TransformerFactory tf = TransformerFactory.newInstance(); + + Transformer serializer = tf.newTransformer(); + serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$ + serializer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ + serializer.transform(domSource, streamResult); + + return true; + } + + /* + * Performs the project renaming operation. The project name in the .project + * files are renamed and any linked directory resources are + * remapped. + * + * @return true if successful otherwise false + */ +/* public boolean performProjectRenaming(IProgressMonitor monitor) throws Exception { + monitor.beginTask( "", projectFiles.length ); //$NON-NLS-1$ + if (parseProjectFile()) { + String projName; + + // get the project name in the .project file + projName = getProjectName(); + if (projName == null) { + monitor.done(); + return false; + } + + // handle the linked directories in the .project file + if (oldLinkPathPrefix != null && newLinkPathPrefix != null + && !oldLinkPathPrefix.equals("")) { //$NON-NLS-1$ + if ( processLinkedResources(oldLinkPathPrefix, newLinkPathPrefix) == true ) { + saveProjectFile(); + } + } + + // rename the project name in the .project + String data; + String new_data; + + // process the .project file + data = readFileIntoString(projectFile); + + new_data = data + .replaceAll("\\b" + projName + "\\b", newProjectName); //$NON-NLS-1$//$NON-NLS-2$ + if (!data.equals(new_data)) { + writeStringIntoFile(projectFile, new_data); + } + monitor.worked(1); + IExecutableExtension[] extensions = getMigrationHelpers(); + if( extensions.length == 0 ) { + monitor.done(); + return true; + } + for( int i = 0; i < projectFiles.length; i++ ) { + if( projectFiles[i].getName().equals(IProjectDescription.DESCRIPTION_FILE_NAME) ) { + continue; + } + + + for( int j = 0; j < extensions.length; j ++ ) { + if (extensions[j] instanceof ProjectMigrationHelper) { + ProjectMigrationHelper helper = (ProjectMigrationHelper) extensions[j]; + IPath filePath = projectPath.append( projectFiles[i].getName()); + helper.migrateFile( filePath, projName, newProjectName, oldLinkPathPrefix, newLinkPathPrefix); + } + } + monitor.worked(1); + } + } + + monitor.done(); + return true; + } + */ + /* + * Get the set of migration helpers. We don't match on the natures since no + * projects are actually open. Instead, the migration helper must "know" which + * files it can help migrate. + */ + /* + private IExecutableExtension[] getMigrationHelpers() { + List helpers = new ArrayList(); + + try { + IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_MIGRATION_HELPERS); + if (extension != null) { + IExtension[] extensions = extension.getExtensions(); + for (int i = 0; i < extensions.length; i++ ) { + IExtension extension2 = extensions[i]; + IConfigurationElement[] configElements = extension2.getConfigurationElements(); + for ( int j = 0; j < configElements.length; j ++ ) { + IConfigurationElement configElement = configElements[j]; + if( configElement.getAttribute( "class" ) != null ) { //$NON-NLS-1$ + helpers.add( configElement.createExecutableExtension("class")); //$NON-NLS-1$ + } + } + } + } + } catch (CoreException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status( IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, Messages.getString("ExportProjectMigrationInfo.4"), e)); //$NON-NLS-1$ + } + + return (IExecutableExtension[]) helpers.toArray(new IExecutableExtension[0]); + + } +*/ +} + + Index: src/org/eclipse/core/internal/resources/projectmigration/SnapInfoStore.java =================================================================== RCS file: src/org/eclipse/core/internal/resources/projectmigration/SnapInfoStore.java diff -N src/org/eclipse/core/internal/resources/projectmigration/SnapInfoStore.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/resources/projectmigration/SnapInfoStore.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,190 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006, 2008 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: + * Wind River Systems, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.resources.projectmigration; + +import org.eclipse.core.internal.resources.projectmigration.SnapInfo; + +import java.io.File; +import java.io.RandomAccessFile; +import java.io.IOException; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.CoreException; + +/** + * This class writes and reads a file which represent a snapshot of a particular + * directory and all of its contained files + */ + +public class SnapInfoStore { + String rootPath; // the root directory for the snapshot + File storeFile; // the file to write to or read from + int fileCount; // total number of files in the store + int rootLocals; // number of spaces reserved for local + + // pass-through files in the root directory + + public SnapInfoStore(String rootPath, File storeFile, int rootLocals) { + this.rootPath = rootPath; + this.storeFile = storeFile; + this.rootLocals = rootLocals; + } + + public SnapInfoStore(String rootPath, File storeFile) { + this.rootPath = rootPath; + this.storeFile = storeFile; + this.rootLocals = 0; + } + + public boolean write(IProgressMonitor monitor) { + boolean ret = false; + if (!rootPath.equals("")) { //$NON-NLS-1$ + IFileStore rootStore = EFS.getLocalFileSystem().getStore( + new Path(rootPath)); + IFileInfo info = rootStore.fetchInfo(); + if (info != null && info.exists()) { + try { + storeFile.delete(); + fileCount = 1; + RandomAccessFile out = new RandomAccessFile(storeFile, "rw"); //$NON-NLS-1$ + out.writeInt(0); // will be rewritten with total file count + // write dummy record for root directory + out.writeInt(SnapInfo.ATTRIBUTE_DIRECTORY); + out.writeLong(0); + out.writeLong(0); + IPath path = new Path(rootPath); + String name = path.lastSegment(); + out.writeUTF(name != null ? name : ""); //$NON-NLS-1$ + ret = writeChildren(monitor, out, rootStore); + out.seek(0); + out.writeInt(fileCount); + out.close(); + } catch (IOException e) { + return false; + } + } + } + return ret; + } + + public SnapInfo[] read(IProgressMonitor monitor) { + try { + if (storeFile.exists()) { + RandomAccessFile in = new RandomAccessFile(storeFile, "r"); //$NON-NLS-1$ + int totalCount = in.readInt(); + if (totalCount != 0) { + SnapInfo[] infos = new SnapInfo[totalCount + rootLocals]; + fileCount = 0; + SnapInfo snap = readInfo(in); // read root entry + infos[0] = snap; + fileCount = rootLocals + 1; // reserve for root locals + snap = readChildren(in, 0, infos); + snap.setNextIndex(0); // end of root dir entries + return infos; + } + } + } catch (IOException e) { + return null; + } + return null; + } + + private boolean writeChildren(IProgressMonitor monitor, + RandomAccessFile out, IFileStore parent) { + try { + String[] children = parent.childNames(EFS.NONE, monitor); + out.writeInt(children.length); + for (int i = 0; i < children.length; i++) { + IFileStore store = parent.getChild(children[i]); + // possible speedup if following line calls fetchInfo()? + IFileInfo info = store.fetchInfo(EFS.NONE, monitor); + if (!writeInfo(out, info)) + return false; + if (info.isDirectory() && !writeChildren(monitor, out, store)) + return false; + } + return true; + } catch (CoreException e) { + return false; + } catch (IOException e) { + return false; + } + } + + private boolean writeInfo(RandomAccessFile out, IFileInfo info) { + try { + int attributes = 0; + if (info.getAttribute(EFS.ATTRIBUTE_ARCHIVE)) + attributes |= EFS.ATTRIBUTE_ARCHIVE; + if (info.getAttribute(EFS.ATTRIBUTE_EXECUTABLE)) + attributes |= EFS.ATTRIBUTE_EXECUTABLE; + if (info.getAttribute(EFS.ATTRIBUTE_HIDDEN)) + attributes |= EFS.ATTRIBUTE_HIDDEN; + // if (info.getAttribute(EFS.ATTRIBUTE_SYMLINK)) + // attributes |= EFS.ATTRIBUTE_SYMLINK; + if (info.getAttribute(EFS.ATTRIBUTE_READ_ONLY)) + attributes |= EFS.ATTRIBUTE_READ_ONLY; + if (info.isDirectory()) + attributes |= SnapInfo.ATTRIBUTE_DIRECTORY; + out.writeInt(attributes); + // if ((attributes & EFS.ATTRIBUTE_SYMLINK) != 0) { + // String link = info.getStringAttribute(EFS.ATTRIBUTE_LINK_TARGET); + // out.writeUTF(link); + // } + out.writeLong(info.getLastModified()); + out.writeLong(info.getLength()); + out.writeUTF(info.getName()); + ++fileCount; + return true; + } catch (IOException e) { + return false; + } + } + + private SnapInfo readChildren(RandomAccessFile in, int parentIndex, + SnapInfo[] infos) throws IOException { + SnapInfo snap = null; + int nChildren = in.readInt(); + for (int i = 0; i < nChildren; i++) { + snap = readInfo(in); + infos[fileCount++] = snap; + if (snap.isDirectory()) { + snap.setChildIndex(fileCount); // assume non-empty + SnapInfo last = readChildren(in, fileCount - 1, infos); + if (last != null) + last.setNextIndex(0); // end of this directory + else + snap.setChildIndex(0); // directory was empty + } + snap.setNextIndex(fileCount); + snap.setParentIndex(parentIndex); + } + return snap; + } + + private SnapInfo readInfo(RandomAccessFile in) throws IOException { + int attributes = in.readInt(); + long lastModified = in.readLong(); + long length = in.readLong(); + String name = in.readUTF(); + SnapInfo snap = new SnapInfo(name); + snap.setAttributes(attributes); + snap.setLastModified(lastModified); + snap.setLength(length); + return snap; + } + +} Index: src/org/eclipse/core/resources/projectmigration/ExportProjectMigrationInfo.java =================================================================== RCS file: src/org/eclipse/core/resources/projectmigration/ExportProjectMigrationInfo.java diff -N src/org/eclipse/core/resources/projectmigration/ExportProjectMigrationInfo.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/resources/projectmigration/ExportProjectMigrationInfo.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,305 @@ +/******************************************************************************* + * Copyright (c) 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: + * Wind River Systems, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.resources.projectmigration; + +import org.eclipse.core.internal.resources.projectmigration.Messages; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +//import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +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.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.internal.resources.projectmigration.SFSUtilities; +/** + * + */ +public class ExportProjectMigrationInfo implements IWorkspaceRunnable { + private IProject fProject; // project that is being exported + + + + /** + * + */ + public ExportProjectMigrationInfo(IProject project) { + fProject = project; + } + + private boolean findMatch( String id, String[] list ) { + for( int i = 0; i < list.length; i++ ) { + if( list[i].equalsIgnoreCase( id ) ) { + return true; + } + } + return false; + } + /* + * Get the list of migration helpers that match on at least one of the natures in the project. + * If the nature in the extension is "*", then it matches any project. + * If the nature in the extension is "+", then it matches only if some other extension matches + */ + private IExecutableExtension[] getMigrationHelpers() { + + List helpers = new ArrayList(); + List possibleHelpers = new ArrayList(); + /* + * Get the list of natures for the project and find matching extensions. + */ + try { + String[] natureIds = fProject.getDescription().getNatureIds(); + IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_MIGRATION_HELPERS); + if (extension != null) { + IExtension[] extensions = extension.getExtensions(); + for (int i = 0; i < extensions.length; i++ ) { + IExtension extension2 = extensions[i]; + boolean matchNature = false; + boolean possibleMatch = false; + IConfigurationElement classConfigElement = null; + IConfigurationElement[] configElements = extension2.getConfigurationElements(); + for ( int j = 0; j < configElements.length; j ++ ) { + IConfigurationElement configElement = configElements[j]; + + String natureID = configElement.getAttribute("nature"); //$NON-NLS-1$ + if( natureID != null ) { + if( natureID.equals("+") ) { //$NON-NLS-1$ + possibleMatch = true; // only add to list if something else matches by nature. + } else if( natureID.equals("*") || findMatch( natureID, natureIds ) == true) { //$NON-NLS-1$ + matchNature = true; + } + } + String classID = configElement.getAttribute("class"); //$NON-NLS-1$ + if( classID != null ) { + classConfigElement = configElement; + } + } + + if( matchNature == true && classConfigElement != null ) { + helpers.add( classConfigElement.createExecutableExtension("class")); //$NON-NLS-1$ + } else { + if( possibleMatch == true && classConfigElement != null ) { + possibleHelpers.add( classConfigElement.createExecutableExtension("class")); //$NON-NLS-1$ + } + } + } + if( possibleHelpers.size() != 0 && helpers.size() != 0 ) { + possibleHelpers.addAll(helpers); + helpers.clear(); + helpers.addAll(possibleHelpers); + possibleHelpers.clear(); + } + } + } catch (CoreException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status( IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, Messages.getString("ExportProjectMigrationInfo.4"), e)); //$NON-NLS-1$ + } + return (IExecutableExtension[])helpers.toArray( new IExecutableExtension[0]); + + + + } + + /* + * This function needs to do the following: + * 1. Find a MigrationHelper for the given project (must match one of the natures) + * 2. Ask the MigrationHelper to create the zip files for export + * 3. Create the Resource Refresh information. + * 4. Create the zip file containing the resource refresh info and any zip files created by the helper. + * 5. Add placeholders to the zip file to record the names of project files that should be copied + * later when the project migration is done. Empty files will be written to the zip to record the names. + * + * If there is not a migrationHelper, then this operation will not do anything. It should fail. + */ + public void run(IProgressMonitor monitor) throws CoreException { + monitor.beginTask("", 100 ); //$NON-NLS-1$ + monitor.setTaskName(Messages.getString("ExportProjectMigrationInfo.5")); //$NON-NLS-1$ + /* + * Find a MigrationHelper for the given project (must match one of the natures) + */ + IExecutableExtension[] extensions = getMigrationHelpers(); + if( extensions == null || extensions.length == 0 ) { + monitor.done(); + return; + } + + /* + * Ask the helpers to create the zip files for export + */ + List zipFilesForExport = new ArrayList(); + List filesToMigrate = new ArrayList(); +// filesToMigrate.add( IProjectDescription.DESCRIPTION_FILE_NAME ); + for( int i = 0; i < extensions.length; i ++ ) { + if (extensions[i] instanceof ProjectMigrationHelper) { + ProjectMigrationHelper helper = (ProjectMigrationHelper) extensions[i]; + helper.setProject( fProject ); + helper.createExportFiles(new SubProgressMonitor(monitor, 40/extensions.length)); + zipFilesForExport.addAll( helper.getExportZipFiles()); + filesToMigrate.addAll(helper.getFilesToMigrate()); + } + } + + /* + * Create the resource refresh information + */ + monitor.setTaskName(Messages.getString("ExportProjectMigrationInfo.6")); //$NON-NLS-1$ + IProjectDescription desc = fProject.getDescription(); + File tmpfile; + try { + tmpfile = File.createTempFile("tmp", ".snap"); //$NON-NLS-1$//$NON-NLS-2$ + SFSUtilities.exportRefreshInfo(desc, tmpfile, new SubProgressMonitor(monitor, 10)); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.0"), e)); //$NON-NLS-1$ + } + + + /* + * Create the zip file containing the resource refresh info and any zip files created by the helper. + * Files to add to the zip file include + * tmpfile - entry is .projdir.snap + * all files in zipFilesForExport + * placeholders for everything in filesToMigrate + */ + int ticks = 50/(1 + zipFilesForExport.size() + filesToMigrate.size()); + File targetLocationFile = fProject.getLocation().append(ProjectMigration.MIGRATION_ZIP_NAME).toFile(); + targetLocationFile.delete(); + ZipOutputStream out= null; + try { + targetLocationFile.getParentFile().mkdirs(); + out= new ZipOutputStream(new FileOutputStream(targetLocationFile)); + out.setLevel(Deflater.BEST_COMPRESSION); + checkMonitor(monitor); + writeEntry(out, ProjectMigration.SNAP_NAME, tmpfile, new SubProgressMonitor( monitor, ticks )); + for( int i = 0; i < zipFilesForExport.size(); i++) { + ProjectMigrationHelper.ExportZipFileEntryInfo info = (ProjectMigrationHelper.ExportZipFileEntryInfo) zipFilesForExport.get(i); + writeEntry(out, info.getName(), info.getFile(), new SubProgressMonitor( monitor, ticks ) ); + } + for( int i = 0; i < filesToMigrate.size(); i++ ) { + String name = (String) filesToMigrate.get(i); + writePlaceHolder( out, name, new SubProgressMonitor( monitor, ticks ) ); + } + for( int i = 0; i < extensions.length; i ++ ) { + if (extensions[i] instanceof ProjectMigrationHelper) { + ProjectMigrationHelper helper = (ProjectMigrationHelper) extensions[i]; + helper.setProject( fProject ); + helper.removeExportFiles(); + } + } + + } + catch (IOException e) { + throw new CoreException( new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.3"), e)); //$NON-NLS-1$ + + } + finally { + close(out); + } + + /* + * TODO: what is the following code trying to do? (make the .settings part of the project?) + */ +/* IFile[] wsResource= ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(new Path(targetLocationFile.getAbsolutePath())); + for (int i = 0; i < wsResource.length; i++) { + IFile file = wsResource[i]; + file.refreshLocal(0, new NullProgressMonitor()); + } +*/ + monitor.done(); + + } + private void checkMonitor(IProgressMonitor monitor) { + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + } + private void writeEntry(ZipOutputStream out, String name, File input, IProgressMonitor monitor) throws IOException { + monitor.beginTask("", 100); //$NON-NLS-1$ + monitor.subTask(name); + ZipEntry e= new ZipEntry(name); + out.putNextEntry(e); + int read= 0; + byte[] buffer= new byte[4096]; + InputStream in= new FileInputStream(input); + long totalBytes = input.length(); + long totalDone = 0; + try { + while ((read= in.read(buffer)) >= 0) { + out.write(buffer, 0, read); + totalDone += read; + long ticks = (totalDone * 100)/totalBytes; + if( ticks > 0 ) { + monitor.worked( (int)ticks); + totalDone -= (ticks * totalBytes)/100; + } + + } + out.closeEntry(); + } + finally { + close(in); + monitor.done(); + } + } + private void writePlaceHolder(ZipOutputStream out, String name, IProgressMonitor monitor) throws IOException { + monitor.beginTask("", 100); //$NON-NLS-1$ + monitor.subTask(name); + ZipEntry e= new ZipEntry(name); + out.putNextEntry(e); + try { + out.closeEntry(); + } + finally { + monitor.done(); + } + } + private void close(InputStream in) { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + ResourcesPlugin.getPlugin().getLog().log( new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.1"), e)); //$NON-NLS-1$ + } + } + + private void close(OutputStream out) { + try { + if (out != null) { + out.close(); + } + } catch (IOException e) { + ResourcesPlugin.getPlugin().getLog().log( new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.2"), e)); //$NON-NLS-1$ + + } + } + +} Index: src/org/eclipse/core/internal/resources/projectmigration/SFSFileSystem.java =================================================================== RCS file: src/org/eclipse/core/internal/resources/projectmigration/SFSFileSystem.java diff -N src/org/eclipse/core/internal/resources/projectmigration/SFSFileSystem.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/resources/projectmigration/SFSFileSystem.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,373 @@ +/********************************************************************** + * Copyright (c) 2008 Wind River Systems 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: + * Wind River Systems - Initial API and implementation + **********************************************************************/ + +package org.eclipse.core.internal.resources.projectmigration; + +import org.eclipse.core.resources.ResourcesPlugin; + + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; + + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.filesystem.provider.FileSystem; +import org.eclipse.core.filesystem.URIUtil; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; + +/** + * This is the snapshot file system. It reads a snapshot of a file tree, and + * then uses the snapshot information to supply file information to the users of + * the file system. + * + * The URI's for this system are as follows: + * + * snapfs:///?# + * + * For example: + * + * snapfs:///.project?/vob/proj#projdir.snap + * + * The only complicated part is that we allow the user to specify a certain + * number of files, found in the root directory of the snapshot, to be + * "passed through" to the local file system rather than being processed via the + * snapshot information. The number of such files which may be defined is + * specified by the static variable rootLocals, and their names are added to a + * static list. + * + */ + +public class SFSFileSystem extends FileSystem { + public SFSFileSystem() { + super(); + sfsFileSystem = this; + } + + private static SFSFileSystem sfsFileSystem; + + public static final String SCHEME = "snapfs"; //$NON-NLS-1$ + + static private String rootFilePath = null; + static private String[] rootLocalNames; + private SnapInfo[] snapInfos; + static private int rootLocals; + + // same as FileInfo.ATTRIBUTE_DRECTORY which is unfortunately private + static int ATTRIBUTE_DIRECTORY = 1 << 0; + + // Only one snapfs file system can be used at any time, + // although there is currently no protection against this. + // Since the feature is designed to work only during what + // we call "project migration", we assume that such migrations + // will only occur sequentially. The static nature of the + // file system is required because the constructor is called + // from within the EFS (Eclipse File System). + + public static SFSFileSystem getSFSFileSystem() { + return sfsFileSystem; + } + + // Set the root path for the directory tree whose contents is + // described in the snap info file. Also, specify the number + // of "root local" files which will be passed through to the + // local file system. Calling this method activates the use + // of the snapshot file refresh information. + static public void setRootPath(String rootPath, int numberofRootLocals) { + rootFilePath = rootPath; + rootLocals = numberofRootLocals; + rootLocalNames = new String[numberofRootLocals]; + } + + // Load the snapshot from the refresh info file created during + // the migration export operation. This method is called from + // getURI if a non-null root file path is present but the + // "snapInfos" array is null. + private boolean loadSnapshot(IProgressMonitor monitor, String path, + String snapFilePath) { + IPath fullPath = new Path(rootFilePath); + String rootName = fullPath.lastSegment(); + fullPath = fullPath.append(snapFilePath); + File snapFile = new File(fullPath.toString()); + SnapInfoStore store = new SnapInfoStore(path, snapFile, rootLocals); + snapInfos = store.read(monitor); + if (snapInfos == null) { + stopUsingRefreshInfo(); // turn off redirection + return false; + } + snapInfos[0].setName(rootName); // set name of root directory + snapInfos[0].setChildIndex(rootLocals + 1); + // Now check each "pass through" file to see if it is present in + // the snapshot info; if so, adjust the links so it is skipped. + for (int i = 0; i < rootLocals; i++) { + String name = rootLocalNames[i]; + if (name == null) + break; // end of root locals (not all need be used) + int prev = 0; // will update snapInfos[0] if first entry matches + for (int x = rootLocals + 1; x != 0 && x < snapInfos.length;) { + if (snapInfos[x].getName().equals(name)) { + snapInfos[prev].setNextIndex(snapInfos[x].getNextIndex()); + break; + } + prev = x; + x = snapInfos[x].getNextIndex(); + } + // Get the file info from the local file system and place it + // in the snapInfos array. + fullPath = fullPath.removeLastSegments(1).append(name); + IFileStore localStore = EFS.getLocalFileSystem().getStore(fullPath); + IFileInfo info = localStore.fetchInfo(); + SnapInfo snap = new SnapInfo(name); + int attributes = 0; + if (info.getAttribute(EFS.ATTRIBUTE_ARCHIVE)) + attributes |= EFS.ATTRIBUTE_ARCHIVE; + if (info.getAttribute(EFS.ATTRIBUTE_EXECUTABLE)) + attributes |= EFS.ATTRIBUTE_EXECUTABLE; + if (info.getAttribute(EFS.ATTRIBUTE_HIDDEN)) + attributes |= EFS.ATTRIBUTE_HIDDEN; + if (info.getAttribute(EFS.ATTRIBUTE_SYMLINK)) + attributes |= EFS.ATTRIBUTE_SYMLINK; + if (info.getAttribute(EFS.ATTRIBUTE_READ_ONLY)) + attributes |= EFS.ATTRIBUTE_READ_ONLY; + if (info.isDirectory()) + attributes |= ATTRIBUTE_DIRECTORY; + snap.setAttributes(attributes); + snap.setLastModified(info.getLastModified()); + snap.setLength(info.getLength()); + snapInfos[i + 1] = snap; + } + return true; + } + + // Discontinue use of the snapshot file refresh information. + // All further references to elements of this file system are + // forwarded to the local file system. + static public void stopUsingRefreshInfo() { + rootFilePath = null; + rootLocals = 0; + rootLocalNames = null; + if (sfsFileSystem != null) + sfsFileSystem.snapInfos = null; + } + + // Add the name of a "root local file" to the list. Return true + // if successful, or false if no additional root local files can + // be added. Note that a root local file should not be a directory, + // as the algorithm in the childCount method will not work correctly + // in that case. + static public boolean setRootLocalFile(String name) { + for (int i = 0; i < rootLocals; i++) + if (rootLocalNames[i] == null) { + rootLocalNames[i] = name; + return true; + } + return false; + } + + // Check if the index into the snapshot file information is for + // a root local file. (Only to be called from SFSFileStore) + static public boolean isRootLocalFileStore(int snapIndex) { + return snapIndex >= 0 && snapIndex < rootLocals + && rootLocalNames[snapIndex] != null; + } + + // Check if the name is that of a file in the root local file list. + public boolean isRootLocalFile(String name) { + for (int i = 0; i < rootLocals && rootLocalNames[i] != null; i++) + if (rootLocalNames[i].equals(name)) + return true; + return false; + } + + // Return a count of the children of the file identified by "snapIndex". + // (Only to be called from SFSFileStore) + private int childCount(int snapIndex) { + if (snapInfos == null || snapIndex < 0 || snapIndex >= snapInfos.length + || !snapInfos[snapIndex].isDirectory()) { + return 0; + } + int count = 0; + int x = snapInfos[snapIndex].getChildIndex(); + if (snapIndex == 0) { + for (int i = 1; i <= rootLocals && snapInfos[i] != null; i++) + ++count; // count the root locals + } + for (; x != 0 && x < snapInfos.length;) { + ++count; + x = snapInfos[x].getNextIndex(); + } + return count; + } + + // Return the child IFileInfo array for the directory specified + // by "snapIndex". (Only to be called from SFSFileStore) + public IFileInfo[] childInfos(int snapIndex) { + int n = childCount(snapIndex); + if (n == 0) + return new IFileInfo[0]; + IFileInfo[] children = new SnapInfo[n]; + int x = snapInfos[snapIndex].getChildIndex(); + int i = 0; + if (snapIndex == 0) { + for (int j = 1; j <= rootLocals && snapInfos[j] != null; j++) + children[i++] = snapInfos[j]; + } + for (; i < n; i++) { + children[i] = snapInfos[x]; + x = snapInfos[x].getNextIndex(); + } + return children; + } + + // Return the child IFileStore array for the directory specified + // by "snapIndex". (Only to be called from SFSFileStore) + public IFileStore[] childStores(int snapIndex) { + int n = childCount(snapIndex); + if (n == 0) + return new IFileStore[0]; + IFileStore[] children = new SFSFileStore[n]; + int x = snapInfos[snapIndex].getChildIndex(); + int i = 0; + if (snapIndex == 0) { + for (int j = 1; j <= rootLocals && snapInfos[j] != null; j++) { + IPath path = new Path(rootFilePath).append(rootLocalNames[i]); + children[i++] = getStore(path); + } + } + for (; i < n; i++) { + children[i] = new SFSFileStore(x); + x = snapInfos[x].getNextIndex(); + } + return children; + } + + // Return the SnapInfo (an implementor of IFileInfo) for the file + // specified by "snapIndex". (Only to be called from SFSFileStore) + public SnapInfo fetchInfo(int snapIndex) { + if (snapInfos == null || snapIndex < 0 || snapIndex >= snapInfos.length) { + return null; + } + return snapInfos[snapIndex]; + } + + // Return the IFileStore for the named child of the directory + // specified by "snapIndex". (Only to be called from SFSFileStore) + public IFileStore getChild(int snapIndex, String name) { + if (snapInfos == null || snapIndex < 0 || snapIndex >= snapInfos.length + || !snapInfos[snapIndex].isDirectory()) { + return null; // ??? should return something + } + if (snapIndex == 0 && isRootLocalFile(name)) { + IPath path = new Path(rootFilePath); + path = path.append(name); + return EFS.getLocalFileSystem().getStore(path); + } + int x = snapInfos[snapIndex].getChildIndex(); + while (x != 0 && x < snapInfos.length) { + if (snapInfos[x].getName().equals(name)) + return new SFSFileStore(x); + x = snapInfos[x].getNextIndex(); + } + IPath path = new Path(rootFilePath); + path.append(name); + return EFS.getNullFileSystem().getStore(path); + } + + // Return the SFSFileStore (an implementor of IFileStore) for + // the root directory of the file refresh information. + // (Only to be called from SFSFileStore) + public SFSFileStore getRoot() { + if (snapInfos == null) + return null; + return new SFSFileStore(0); + } + + // Return an IFileStore for the specified URI (one which includes + // the "snapfs:" scheme). If use of the refresh info file is not + // currently on, or if there is failure loading the refresh info, + // or if the root file path in the URI (the query portion) is not + // the same as the root file name for the refresh information, or + // if the file specifies a "root local" file, go to the local file + // system for an IFileStore; otherwise, get the SFSFileStore for + // the corresponding file within the refresh information. + public IFileStore getStore(URI uri) { + try { + IPath path = new Path(uri.getPath()); + if (rootFilePath == null + || // use of snapshot is turned off + (snapInfos == null && // or, failure loading snapshot info + !loadSnapshot(null, path.toString(), uri.getFragment())) + || !uri.getQuery().equals(rootFilePath) || // or, not for + // this root + (path.segmentCount() == 1 && // or, a local file + isRootLocalFile(path.lastSegment()))) { + // refer this to local file system + IPath localPath = new Path(uri.getQuery()); + localPath.append(path); + URI localURI = new URI(EFS.SCHEME_FILE, uri.getAuthority(), + localPath.toString(), null, null); + return EFS.getLocalFileSystem().getStore(localURI); + } + SFSFileStore root = getRoot(); + if (path.segmentCount() == 0) + return root; + return root.getChild(path); + } catch (URISyntaxException e) { + ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, + "uri", e)); //$NON-NLS-1$ + // } catch (CoreException e) { + // Activator.log(e); + } + + return EFS.getNullFileSystem().getStore(uri); + } + + public int attributes() { + // return all local file system attributes, even though + // not all files can be written (only pass-through files) + return EFS.getLocalFileSystem().attributes(); + } + + public boolean canDelete() { + return true; + } + + public boolean canWrite() { + return true; + } + + public IFileStore fromLocalFile(File file) { + return EFS.getLocalFileSystem().fromLocalFile(file); + } + + public IFileStore getStore(IPath path) { + return EFS.getLocalFileSystem().getStore(path); + } + + public boolean isCaseSensitive() { + return EFS.getLocalFileSystem().isCaseSensitive(); + } + + public String rootPath() { + return rootFilePath; + } + + public URI rootURI() { + return URIUtil.toURI(new Path(rootFilePath)); + } + +} Index: src/org/eclipse/core/internal/resources/projectmigration/SFSFileStore.java =================================================================== RCS file: src/org/eclipse/core/internal/resources/projectmigration/SFSFileStore.java diff -N src/org/eclipse/core/internal/resources/projectmigration/SFSFileStore.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/resources/projectmigration/SFSFileStore.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,203 @@ +/********************************************************************** + * Copyright (c) 2008 Wind River Systems 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: + * Wind River Systems - Initial API and implementation + **********************************************************************/ + +package org.eclipse.core.internal.resources.projectmigration; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.filesystem.IFileSystem; +import org.eclipse.core.filesystem.provider.FileStore; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; + +public class SFSFileStore extends FileStore { + private int snapIndex; + private static final String[] nullStringArray = new String[0]; + + public SFSFileStore(int snapIndex) { + this.snapIndex = snapIndex; + } + + + /** + * @throws CoreException + * @Override + */ + public IFileInfo[] childInfos(int options, IProgressMonitor monitor) + throws CoreException { + return SFSFileSystem.getSFSFileSystem().childInfos(snapIndex); + } + + /** + * @throws CoreException + * @Override + */ + public String[] childNames(int options, IProgressMonitor monitor) + throws CoreException { + IFileInfo[] infos = SFSFileSystem.getSFSFileSystem().childInfos(snapIndex); + if (infos == null || infos.length == 0) + return nullStringArray; + String[] children = new String[infos.length]; + for (int i = 0; i < infos.length; i++) { + children[i] = infos[i].getName(); + } + return children; + } + + /** + * @throws CoreException + * @Override + */ + public IFileStore[] childStores(int options, IProgressMonitor monitor) + throws CoreException { + return SFSFileSystem.getSFSFileSystem().childStores(snapIndex); + } + + //@Override + public void copy(IFileStore destination, int options, + IProgressMonitor monitor) throws CoreException { + super.copy(destination, options, monitor); + } + + //@Override + protected void copyDirectory(IFileInfo sourceInfo, IFileStore destination, + int options, IProgressMonitor monitor) throws CoreException { + super.copyDirectory(sourceInfo, destination, options, monitor); + } + + //@Override + protected void copyFile(IFileInfo sourceInfo, IFileStore destination, + int options, IProgressMonitor monitor) throws CoreException { + super.copyFile(sourceInfo, destination, options, monitor); + } + + //@Override + public void delete(int options, IProgressMonitor monitor) + throws CoreException { + super.delete(options, monitor); + } + + //@Override + public IFileInfo fetchInfo() { + return SFSFileSystem.getSFSFileSystem().fetchInfo(snapIndex); + } + + /** + * @throws CoreException + * @Override + */ + public IFileInfo fetchInfo(int options, IProgressMonitor monitor) + throws CoreException { + return fetchInfo(); + } + + //@Override + public IFileStore getChild(String name) { + return SFSFileSystem.getSFSFileSystem().getChild(snapIndex, name); + } + + //@Override + public IFileSystem getFileSystem() { + return SFSFileSystem.getSFSFileSystem(); + } + + //@Override + public String getName() { + IFileInfo info = SFSFileSystem.getSFSFileSystem().fetchInfo(snapIndex); + if (info != null) + return info.getName(); + return null; + } + + //@Override + public /*SFS*/IFileStore getParent() { + SnapInfo snapInfo = SFSFileSystem.getSFSFileSystem().fetchInfo( + snapIndex); + return new SFSFileStore(snapInfo.getParentIndex()); + } + + //@Override + public IFileStore mkdir(int options, IProgressMonitor monitor) + throws CoreException { + return super.mkdir(options, monitor); + } + + //@Override + public void move(IFileStore destination, int options, + IProgressMonitor monitor) throws CoreException { + super.move(destination, options, monitor); + } + + //@Override + public InputStream openInputStream(int options, IProgressMonitor monitor) + throws CoreException { + IPath path = getPath(); + return SFSFileSystem.getSFSFileSystem().getStore(path).openInputStream( + options, monitor); + } + + //@Override + public OutputStream openOutputStream(int options, IProgressMonitor monitor) + throws CoreException { + return super.openOutputStream(options, monitor); + } + + //@Override + public URI toURI() { + + URI rootURI = SFSFileSystem.getSFSFileSystem().rootURI(); + + // Build path + IPath path = getPath(); + String pathstr = path == null ? null : getPath().toString(); + + try { + URI uri = new URI(SFSFileSystem.SCHEME, rootURI.getAuthority(), + rootURI.getPath(), pathstr, rootURI.getScheme()); + return uri; + } catch (URISyntaxException e) { + return null; + } + } + + public IPath getPath() { + SnapInfo snapInfo = SFSFileSystem.getSFSFileSystem().fetchInfo(snapIndex); + if (snapInfo.getParentIndex() == 0) { + // Parent is root, start at this node + IPath path = new Path(SFSFileSystem.getSFSFileSystem().rootPath()); + if (this.snapIndex != 0) + path = path.append(getName()); + return path; + } + // Normal path creation + return ((SFSFileStore)getParent()).getPath().append(getName()); + } + + //@Override + public File toLocalFile(int options, IProgressMonitor monitor) + throws CoreException { + if ((options & EFS.CACHE) != 0) + return super.toLocalFile(options, monitor); + if (!SFSFileSystem.isRootLocalFileStore(snapIndex)) + return null; + return new File(getPath().toString()); + } + +} #P org.eclipse.ui.ide Index: plugin.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.ide/plugin.properties,v retrieving revision 1.142 diff -u -r1.142 plugin.properties --- plugin.properties 19 Jan 2009 14:35:31 -0000 1.142 +++ plugin.properties 24 Mar 2009 21:22:22 -0000 @@ -28,9 +28,11 @@ ExportWizards.FileSystem = File System ExportWizards.Preferences = Preferences ExportWizards.ZipFile = Archive File +ExportWizards.ProjectMigrationExport = Project Migration Preparation ExportWizards.FileSystemDescription = Export resources to the local file system. ExportWizards.PreferencesDescription = Export preferences to the local file system. ExportWizards.ZipFileDescription = Export resources to an archive file on the local file system. +ExportWizards.ProjectMigrationDescription = Export a snapshot of project information needed for a project migration. ImportWizards.FileSystem = File System ImportWizards.Preferences = Preferences ImportWizards.ZipFile = Archive File @@ -39,6 +41,7 @@ ImportWizards.PreferencesDescription = Import preferences from the local file system. ImportWizards.ZipFileDescription = Import resources from an archive file into an existing project. ImportWizards.ExternalProjectDescription = Create new projects from an archive file or directory. +ImportWizards.ProjectMigration = Migrate existing project to a new project directory NewWizards.Category.Examples = Examples NewWizards.Category.Basic = General NewWizards.project = Project Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.ide/plugin.xml,v retrieving revision 1.283 diff -u -r1.283 plugin.xml --- plugin.xml 19 Jan 2009 14:35:31 -0000 1.283 +++ plugin.xml 24 Mar 2009 21:22:23 -0000 @@ -66,6 +66,13 @@ class="org.eclipse.core.resources.IResource"> + + @@ -111,6 +118,19 @@ class="org.eclipse.core.resources.IResource"> + + + + + %ExportWizards.ProjectMigrationDescription + + Index: src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationOperation.java =================================================================== RCS file: src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationOperation.java diff -N src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationOperation.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationOperation.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006, 2008 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: + * Wind River Systems, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.wizards.projectmigration; + +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; + +import org.eclipse.core.resources.projectmigration.ProjectMigration; +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.Status; + +import org.eclipse.ui.dialogs.IOverwriteQuery; + +import org.eclipse.ui.actions.WorkspaceModifyOperation; + +/** + * An operation which does the actual work of importing a migrated project into + * the workspace. + *

+ * This class may be instantiated; it is not intended to be subclassed. + *

+ */ +public class ProjectMigrationOperation extends WorkspaceModifyOperation { + + private IPath sourcePath; + + private IPath destinationPath; + + private String newProjectName; + + private String oldLinkedPathPrefix; + + private String newLinkedPathPrefix; + + //private boolean ignoreIndex; + + //private boolean ignoreFileInfo; + + protected IOverwriteQuery overwriteCallback; + + /** + * Creates a new operation that performs a "trusted import" of the specified + * project. This means that the file stat information and the PDOM from the + * source project are to be imported and trusted, i.e., not verified. + *

+ * The sourceObject parameter represents the directory + * containing the project to import. + *

+ * @param destinationPath + * full path of destination directory + * @param sourcePath + * file system object for project to import + * @param newProjName + * @param oldLinkedPathPrefix + * @param newLinkedPathPrefix + */ + public ProjectMigrationOperation(IPath sourcePath, + String newProjName, IPath destinationPath, + String oldLinkedPathPrefix, String newLinkedPathPrefix ) { + super(); + this.sourcePath = sourcePath; + this.destinationPath = destinationPath; + this.newProjectName = newProjName; + this.oldLinkedPathPrefix = oldLinkedPathPrefix; + this.newLinkedPathPrefix = newLinkedPathPrefix; + //this.ignoreIndex = ignoreIndex; + //this.ignoreFileInfo = ignoreFileInfo; + } + + /* + * (non-Javadoc) Method declared on WorkbenchModifyOperation. Imports the + * specified project from the file system. + */ + protected void execute(IProgressMonitor monitor) throws CoreException { + ProjectMigration pm = new ProjectMigration( sourcePath, newProjectName, destinationPath); + + pm.setLinkedPathPrefix(oldLinkedPathPrefix, newLinkedPathPrefix); + //pm.setIgnoreIndex(ignoreIndex); + //pm.setIgnoreFileInfo(ignoreFileInfo); + + try { + monitor + .beginTask( + Messages.getString("ProjectMigrationOperation.0"), //$NON-NLS-1$ + 100); + pm.execute(monitor); + } catch (Exception e) { + throw new CoreException(new Status(IStatus.ERROR, + IDEWorkbenchPlugin.IDE_WORKBENCH, 0, Messages.getString("ProjectMigrationOperation.1"), e)); //$NON-NLS-1$ + } finally { + monitor.done(); + } + } + +} Index: src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationExportWizard.java =================================================================== RCS file: src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationExportWizard.java diff -N src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationExportWizard.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationExportWizard.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. 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: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.wizards.projectmigration; + +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.ui.IExportWizard; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; +import org.eclipse.ui.internal.wizards.projectmigration.Messages; + +/** + * @since 3.4 + * + */ +public class ProjectMigrationExportWizard extends Wizard implements IExportWizard { + private static final String DIALOG_SETTINGS_SECTION = "ProjectMigrationExportWizard"; //$NON-NLS-1$ + private ProjectMigrationExportWizardPage fMainPage; + private IStructuredSelection fSelection; + + /** + * + */ + public ProjectMigrationExportWizard() { + IDialogSettings workbenchSettings = IDEWorkbenchPlugin.getDefault().getDialogSettings(); + IDialogSettings section = workbenchSettings.getSection(DIALOG_SETTINGS_SECTION); + if (section == null) { + section = workbenchSettings.addNewSection(DIALOG_SETTINGS_SECTION); + } + setDialogSettings(section); + } + + //@Override + public void addPages() { + super.addPages(); + fMainPage = new ProjectMigrationExportWizardPage(fSelection); + addPage(fMainPage); + } + + //@Override + public boolean performFinish() { + return fMainPage.finish(); + } + + public void init(IWorkbench workbench, IStructuredSelection selection) { + fSelection= selection; + setWindowTitle(Messages.getString("ProjectMigrationExportWizard.0")); //$NON-NLS-1$ + setDefaultPageImageDescriptor(IDEWorkbenchPlugin.getIDEImageDescriptor("wizban/exportzip_wiz.png")); //$NON-NLS-1$ + setNeedsProgressMonitor(true); + } + +} Index: src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationWizard.java =================================================================== RCS file: src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationWizard.java diff -N src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationWizard.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationWizard.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 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 + *******************************************************************************/ +package org.eclipse.ui.internal.wizards.projectmigration; + +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.ui.IImportWizard; +import org.eclipse.ui.IWorkbench; +//import org.eclipse.ui.internal.WorkbenchImages; +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; + + + +//import org.eclipse.cdt.internal.ui.CPluginImages; +//import org.eclipse.cdt.internal.ui.wizards.projectmigration.ProjectMigrationMessages; +//import org.eclipse.cdt.internal.ui.wizards.projectmigration.WizardProjectsMigrationPage; + +/** + * Standard workbench wizard for importing projects defined outside of the + * currently defined projects into Eclipse. + *

+ * This class may be instantiated and used without further configuration; this + * class is not intended to be subclassed. + *

+ *

+ * Example: + * + *

+ * IWizard wizard = new ProjectMigrationWizard();
+ * wizard.init(workbench, selection);
+ * WizardDialog dialog = new WizardDialog(shell, wizard);
+ * dialog.open();
+ * 
+ * + * During the call to open, the wizard dialog is presented to the + * user. When the user hits Finish, a project is created with the location + * specified by the user. + *

+ */ + +public class ProjectMigrationWizard extends Wizard implements + IImportWizard { + private static final String EXTERNAL_PROJECT_SECTION = "ProjectMigrationWizard";//$NON-NLS-1$ + private ProjectMigrationWizardPage mainPage; + + /** + * Constructor for ProjectMigrationWizard. + */ + public ProjectMigrationWizard() { + super(); + setNeedsProgressMonitor(true); + IDialogSettings workbenchSettings = IDEWorkbenchPlugin.getDefault() + .getDialogSettings(); + + IDialogSettings wizardSettings = workbenchSettings + .getSection(EXTERNAL_PROJECT_SECTION); + if (wizardSettings == null) { + wizardSettings = workbenchSettings + .addNewSection(EXTERNAL_PROJECT_SECTION); + } + setDialogSettings(wizardSettings); + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public void addPages() { + super.addPages(); + mainPage = new ProjectMigrationWizardPage(); + addPage(mainPage); + } + + /* + * (non-Javadoc) Method declared on IWorkbenchWizard. + */ + public void init(IWorkbench workbench, IStructuredSelection currentSelection) { + setWindowTitle(Messages.getString("ProjectMigrationWizard.0")); //$NON-NLS-1$ + setDefaultPageImageDescriptor(IDEWorkbenchPlugin.getIDEImageDescriptor("wizban/importproj_wiz.png")); //$NON-NLS-1$ + //setDefaultPageImageDescriptor(WorkbenchImages.DESC_WIZBAN_MIGRATEPROJ); + // CUIPlugin.getIDEImageDescriptor("wizban/importproj_wiz.png")); //$NON-NLS-1$ + + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public boolean performCancel() { + mainPage.performCancel(); + return true; + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public boolean performFinish() { + return mainPage.createProjects(); + } + +} Index: src/org/eclipse/ui/internal/wizards/projectmigration/Messages.java =================================================================== RCS file: src/org/eclipse/ui/internal/wizards/projectmigration/Messages.java diff -N src/org/eclipse/ui/internal/wizards/projectmigration/Messages.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/wizards/projectmigration/Messages.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. 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: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.wizards.projectmigration; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * @since 3.4 + * + */ +public class Messages { + private static final String BUNDLE_NAME = "org.eclipse.ui.internal.wizards.projectmigration.messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME); + + private Messages() { + /* + * no initialization needed + */ + } + + /** + * @param key + * @return a String corresponding to the key. + */ + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + +} Index: src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationExportWizardPage.java =================================================================== RCS file: src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationExportWizardPage.java diff -N src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationExportWizardPage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationExportWizardPage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,385 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. 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: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.wizards.projectmigration; + +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 org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.projectmigration.ExportProjectMigrationInfo; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.SubProgressMonitor; + +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.Viewer; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +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.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.dialogs.WizardDataTransferPage; +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; +import org.eclipse.ui.internal.wizards.projectmigration.Messages; +import org.eclipse.ui.model.WorkbenchLabelProvider; + + + +/** + * @since 3.4 + * + */ +public class ProjectMigrationExportWizardPage extends WizardDataTransferPage { + + private IStructuredSelection fInitialSelection; + private CheckboxTableViewer fProjectViewer; + + + /** + * Create an instance of this class + */ + protected ProjectMigrationExportWizardPage(String name, IStructuredSelection selection) { + super(name); + fInitialSelection= selection; + } + + /** + * Create an instance of this class. + * + * @param selection the selection + */ + public ProjectMigrationExportWizardPage(IStructuredSelection selection) { + this("indexExportPage", selection); //$NON-NLS-1$ + setTitle(Messages.getString("ProjectMigrationExportWizardPage.0")); //$NON-NLS-1$ + setDescription(Messages.getString("ProjectMigrationExportWizardPage.1")); //$NON-NLS-1$ + } + + public void createControl(Composite parent) { + initializeDialogUnits(parent); + + Composite composite = new Composite(parent, SWT.NULL); + composite.setLayout(new GridLayout()); + composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL + | GridData.HORIZONTAL_ALIGN_FILL)); + composite.setFont(parent.getFont()); + + createResourcesGroup(composite); + createDestinationGroup(composite); + createOptionsArea(composite); + + restoreWidgetValues(); + if (fInitialSelection != null) { + setupBasedOnInitialSelections(); + } + //setupDestination(); + + updateWidgetEnablements(); + setPageComplete(determinePageCompletion()); + setErrorMessage(null); // should not initially have error message + + setControl(composite); + } + + /** + * Creates the checkbox tree and list for selecting resources. + * + * @param parent the parent control + */ + private final void createResourcesGroup(Composite parent) { + Composite resourcesGroup = new Composite(parent, SWT.NONE); + resourcesGroup.setLayout(new GridLayout()); + resourcesGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); + resourcesGroup.setFont(parent.getFont()); + + new Label(resourcesGroup, SWT.NONE).setText(Messages.getString("ProjectMigrationExportWizardPage.2")); //$NON-NLS-1$ + Table table= new Table(resourcesGroup, SWT.CHECK | SWT.BORDER); + table.setLayoutData(new GridData(GridData.FILL_BOTH)); + fProjectViewer= new CheckboxTableViewer(table); + fProjectViewer.setContentProvider(new IStructuredContentProvider() { + List fContents; + + public Object[] getElements(Object input) { + if (fContents != null && fContents == input) + return fContents.toArray(); + return new Object[0]; + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + if (newInput instanceof List) + fContents= (List)newInput; + else + fContents= null; + // we use a fixed set. + } + + public void dispose() { + } + + + } ); + fProjectViewer.setLabelProvider(new WorkbenchLabelProvider()); + ICheckStateListener checkListener = new ICheckStateListener() { + public void checkStateChanged(CheckStateChangedEvent event) { + updateWidgetEnablements(); + } + }; + fProjectViewer.addCheckStateListener(checkListener); + + + // top level group + Composite buttonComposite = new Composite(resourcesGroup, SWT.NONE); + buttonComposite.setFont(parent.getFont()); + + GridLayout layout = new GridLayout(2, true); + layout.marginHeight= layout.marginWidth= 0; + buttonComposite.setLayout(layout); + buttonComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL + | GridData.HORIZONTAL_ALIGN_FILL)); + + + Button selectButton = createButton(buttonComposite, + IDialogConstants.SELECT_ALL_ID, Messages.getString("ProjectMigrationExportWizardPage.3"), false); //$NON-NLS-1$ + + SelectionAdapter listener = new SelectionAdapter() { + //@Override + public void widgetSelected(SelectionEvent e) { + fProjectViewer.setAllChecked(true); + updateWidgetEnablements(); + } + }; + selectButton.addSelectionListener(listener); + + Button deselectButton = createButton(buttonComposite, + IDialogConstants.DESELECT_ALL_ID, Messages.getString("ProjectMigrationExportWizardPage.4"), false); //$NON-NLS-1$ + + listener = new SelectionAdapter() { + //@Override + public void widgetSelected(SelectionEvent e) { + fProjectViewer.setAllChecked(false); + updateWidgetEnablements(); + } + }; + deselectButton.addSelectionListener(listener); + + initProjects(); + } + + private Button createButton(Composite parent, int id, String label, + boolean defaultButton) { + Button button = new Button(parent, SWT.PUSH); + + GridData buttonData = new GridData(GridData.FILL_HORIZONTAL); + button.setLayoutData(buttonData); + + button.setData(new Integer(id)); + button.setText(label); + button.setFont(parent.getFont()); + + if (defaultButton) { + Shell shell = parent.getShell(); + if (shell != null) { + shell.setDefaultButton(button); + } + button.setFocus(); + } + button.setFont(parent.getFont()); + setButtonLayoutData(button); + return button; + } + + private void initProjects() { + ArrayList input = new ArrayList(); + IProject[] projects; + projects = IDEWorkbenchPlugin.getPluginWorkspace().getRoot().getProjects(); + for (int i = 0; i < projects.length; i++) { + if (projects[i].isOpen()) { + input.add(projects[i]); + } + } + fProjectViewer.setInput(input); + } + + private void setupBasedOnInitialSelections() { + HashSet names= new HashSet(); + Iterator it = fInitialSelection.iterator(); + while (it.hasNext()) { + IProject project = (IProject) it.next(); + names.add(project.getName()); + } + + Collection prjsc= (Collection) fProjectViewer.getInput(); + Object[] prjs= prjsc.toArray(); + for (int i = 0; i < prjs.length; i++) { + Object element = prjs[i]; + IProject prj = (IProject) element; + if (names.contains(prj.getName())) { + fProjectViewer.setChecked(prj, true); + } + } + } + + + + + private void createDestinationGroup(Composite parent) { + Font font = parent.getFont(); + // destination specification group + Composite destinationSelectionGroup = new Composite(parent, SWT.NONE); + destinationSelectionGroup.setLayout(new GridLayout(2, false)); + destinationSelectionGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL)); + destinationSelectionGroup.setFont(font); + + + } + + /** + * Create the area with the extra options. + * + * @param workArea + */ + private void createOptionsArea(Composite workArea) { + Composite optionsGroup = new Composite(workArea, SWT.NONE); + optionsGroup.setLayout(new GridLayout()); + optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + } + + + /** + * @return Return true to indicate that the operation was a success + * + */ + public boolean finish() { + IProject[] projectsToExport= getCheckedElements(); + + // about to invoke the operation so save our state + saveWidgetValues(); + + return executeExportOperation(projectsToExport); + } + + private IProject[] getCheckedElements() { + Object[] obj= fProjectViewer.getCheckedElements(); + IProject[] prjs= new IProject[obj.length]; + System.arraycopy(obj, 0, prjs, 0, obj.length); + return prjs; + } + + private boolean executeExportOperation(final IProject[] projects) { + //final String dest= getDestinationValue(); + final MultiStatus status= new MultiStatus(IDEWorkbenchPlugin.IDE_WORKBENCH, + 0, Messages.getString("ProjectMigrationExportWizardPage.5"), null); //$NON-NLS-1$ + + IRunnableWithProgress op= new IRunnableWithProgress() { + /** + * @throws InvocationTargetException + * @throws InterruptedException + */ + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + monitor.beginTask("", projects.length); //$NON-NLS-1$ + for( int i = 0; i < projects.length; i++ ) { + IProject project = projects[i]; + ExportProjectMigrationInfo op = new ExportProjectMigrationInfo( project ); + + try { + op.run(new SubProgressMonitor(monitor, 1)); + } catch (CoreException e) { + status.merge(e.getStatus()); + } + } + } + }; + try { + getContainer().run(true, true, op); + } catch (InterruptedException e) { + return false; + } catch (InvocationTargetException e) { + IDEWorkbenchPlugin.log(Messages.getString("ProjectMigrationExportWizardPage.5"), //$NON-NLS-1$ + e.getTargetException()); + displayErrorDialog(e.getTargetException()); + return false; + } + + if (!status.isOK()) { + IDEWorkbenchPlugin.log("",status); //$NON-NLS-1$ + ErrorDialog.openError(getContainer().getShell(), + getErrorDialogTitle(), + null, // no special message + status); + return false; + } + + return true; + } + + + + + //@Override + protected boolean validateSourceGroup() { + // there must be some resources selected for Export + boolean isValid = true; + Object[] projectsToExport = getCheckedElements(); + if (projectsToExport.length == 0){ + setErrorMessage(Messages.getString("ProjectMigrationExportWizardPage.7")); //$NON-NLS-1$ + isValid = false; + } else { + setErrorMessage(null); + } + return super.validateSourceGroup() && isValid; + } + + //@Override + protected void updateWidgetEnablements() { + boolean pageComplete = determinePageCompletion(); + setPageComplete(pageComplete); + if (pageComplete) { + setMessage(null); + } + super.updateWidgetEnablements(); + } + + + public void handleEvent(Event event) { + updateWidgetEnablements(); + } + + //@Override + protected String getErrorDialogTitle() { + return Messages.getString("ProjectMigrationExportWizardPage.8"); //$NON-NLS-1$ + } + + //@Override + protected boolean allowNewContainerName() { + return false; + } +} Index: src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationWizardPage.java =================================================================== RCS file: src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationWizardPage.java diff -N src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationWizardPage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationWizardPage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,1151 @@ +/******************************************************************************* + * Copyright (c) 2004, 2008 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 + *******************************************************************************/ +package org.eclipse.ui.internal.wizards.projectmigration; + +import java.io.*; +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.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.Status; +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.IDialogSettings; +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.ICheckStateListener; +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.wizard.WizardPage; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +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.Label; +import org.eclipse.swt.widgets.Text; + +//import org.eclipse.cdt.core.CCorePlugin; +//import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.ui.actions.WorkspaceModifyOperation; + +import org.eclipse.ui.dialogs.IOverwriteQuery; +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; +import org.eclipse.ui.statushandlers.StatusManager; + +/** + * The ProjectMigrationWizardPage is the page that allows the user to import + * projects from a particular location. + */ +public class ProjectMigrationWizardPage extends WizardPage implements + IOverwriteQuery { + + /** + * The name of the folder containing metadata information for the workspace. + */ + public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$ + + /** + * Class declared public only for test suite. + * + */ + public class ProjectRecord { + File projectSystemFile; + + String projectName; + + Object parent; + + int level; + + IProjectDescription description; + + /** + * Create a record for a project based on the info in the file. + * + * @param file + */ + ProjectRecord(File file) { + projectSystemFile = file; + setProjectName(); + } + + /** + * Set the name of the project based on the projectFile. + */ + private void setProjectName() { + try { + + // If we don't have the project name try again + if (projectName == null) { + IPath path = new Path(projectSystemFile.getPath()); + // if the file is in the default location, use the directory + // name as the project name + if (isDefaultLocation(path)) { + projectName = path.segment(path.segmentCount() - 2); + description = IDEWorkbenchPlugin.getPluginWorkspace() + .newProjectDescription(projectName); + } else { + description = IDEWorkbenchPlugin.getPluginWorkspace() + .loadProjectDescription(path); + projectName = description.getName(); + } + + } + } catch (CoreException e) { + // no good couldn't get the name + } + } + + /** + * 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 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; + } + + /** + * Gets the label to be used when rendering this project record in the + * UI. + * + * @return String the label + * @since 3.4 + */ + public String getProjectLabel() { + if (description == null) + return projectName; + + String path = projectSystemFile.getParent(); + + return NLS + .bind( + Messages.getString("ProjectMigrationWizardPage.0"), //$NON-NLS-1$ + projectName, path); + } + } + + // dialog store id constants + //private final static String STORE_IGNORE_EXPORTED_INDEX_ID = "ProjectMigrationWizardPage.STORE_IGNORE_EXPORTED_INDEX_ID"; //$NON-NLS-1$ + + //private final static String STORE_IGNORE_EXPORTED_PROJECT_ID = "ProjectMigrationWizardPage.STORE_IGNORE_EXPORTED_PROJECT_ID"; //$NON-NLS-1$ + + //private final static String STORE_SHOW_TIMING_PROJECT_ID = "ProjectMigrationWizardPage.STORE_SHOW_TIMING_PROJECT_ID"; //$NON-NLS-1$ + + private Text directoryPathField; + + private Text directoryDestinationPathField; + + private Text newProjectNameField; + + private Text oldLinkedPathPrefixField; + + private Text newLinkedPathPrefixField; + + private CheckboxTreeViewer projectsList; + + //private Button ignoreExportedIndexCheckbox; + + //private Button ignoreExportedProjectRefreshCheckBox; + + //private Button showTimingCheckBox; + + //private boolean ignoreExportedIndex = false; + + //private boolean ignoreExportedProjectRefresh = false; + + //private boolean showTiming = false; + + private ProjectRecord[] selectedProjects = new ProjectRecord[0]; + + // Keep track of the directory that we browsed to last time + // the wizard was invoked. + private static String previouslyBrowsedDirectory = ""; //$NON-NLS-1$ + + private static String previouslyBrowsedDestinationDirectory = ""; //$NON-NLS-1$ + + private Button browseDirectoriesButton; + + private Button browseDestinationDirectoryButton; + + 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; + + /** + * Creates a new project creation wizard page. + * + */ + public ProjectMigrationWizardPage() { + this("wizardExternalProjectsPage"); //$NON-NLS-1$ + } + + /** + * Create a new instance of the receiver. + * + * @param pageName + */ + public ProjectMigrationWizardPage(String pageName) { + super(pageName); + setPageComplete(false); + setTitle(Messages.getString("ProjectMigrationWizardPage.1")); //$NON-NLS-1$ + setDescription(Messages.getString("ProjectMigrationWizardPage.2")); //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets + * .Composite) + */ + 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)); + + createProjectsRoot(workArea); + createProjectsList(workArea); + createLinkedPathPrefixArea(workArea); + createDestinationArea(workArea); + createOptionsArea(workArea); + restoreWidgetValues(); + Dialog.applyDialogFont(workArea); + + } + + /** + * Create the area with the extra options. + * + * @param workArea + */ + private void createOptionsArea(Composite workArea) { + Composite optionsGroup = new Composite(workArea, SWT.NONE); + optionsGroup.setLayout(new GridLayout()); + optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + } + + private void checkForComplete() { + if (projectsList.getCheckedElements().length == 1) { + String path = directoryDestinationPathField.getText().trim(); + if (path.length() > 0) { + File dirpath = new File(path); + if (dirpath.exists()) { + setPageComplete(true); + return; + } + } + } + + setPageComplete(false); + } + + /** + * Create the checkbox list for the found projects. + * + * @param workArea + */ + private void createProjectsList(Composite workArea) { + + Label title = new Label(workArea, SWT.NONE); + title + .setText(Messages.getString("ProjectMigrationWizardPage.3")); //$NON-NLS-1$ + + Composite listComposite = new Composite(workArea, SWT.NONE); + 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 listData = new GridData(GridData.GRAB_HORIZONTAL + | GridData.GRAB_VERTICAL | GridData.FILL_BOTH); + listData.heightHint = 100; + projectsList.getControl().setLayoutData(listData); + + projectsList.setContentProvider(new ITreeContentProvider() { + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java + * .lang.Object) + */ + public Object[] getChildren(Object parentElement) { + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.IStructuredContentProvider#getElements + * (java.lang.Object) + */ + public Object[] getElements(Object inputElement) { + return getValidProjects(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java + * .lang.Object) + */ + public boolean hasChildren(Object element) { + return false; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java + * .lang.Object) + */ + public Object getParent(Object element) { + return null; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse + * .jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, + Object newInput) { + } + + }); + + projectsList.setLabelProvider(new LabelProvider() { + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + */ + public String getText(Object element) { + return ((ProjectRecord) element).getProjectLabel(); + } + }); + + projectsList.addCheckStateListener(new ICheckStateListener() { + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged + * (org.eclipse.jface.viewers.CheckStateChangedEvent) + */ + public void checkStateChanged(CheckStateChangedEvent event) { + checkForComplete(); + } + }); + + projectsList.setInput(this); + projectsList.setComparator(new ViewerComparator()); + } + + /** + * Create the checkbox list for the found projects. + * + * @param workArea + */ + private void createLinkedPathPrefixArea(Composite workArea) { + + // project specification group + Composite projectGroup = new Composite(workArea, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + layout.makeColumnsEqualWidth = false; + layout.marginWidth = 0; + projectGroup.setLayout(layout); + projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // old linked directory path + Label oldLinkedPathLabel = new Label(projectGroup, SWT.NONE); + oldLinkedPathLabel + .setText(Messages.getString("ProjectMigrationWizardPage.4")); //$NON-NLS-1$ + + this.oldLinkedPathPrefixField = new Text(projectGroup, SWT.BORDER); + + this.oldLinkedPathPrefixField.setLayoutData(new GridData( + GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); + + // new linked directory path + Label newLinkedPathLabel = new Label(projectGroup, SWT.NONE); + newLinkedPathLabel + .setText(Messages.getString("ProjectMigrationWizardPage.5")); //$NON-NLS-1$ + + this.newLinkedPathPrefixField = new Text(projectGroup, SWT.BORDER); + + this.newLinkedPathPrefixField.setLayoutData(new GridData( + GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); + + } + + /** + * Create the checkbox list for the found projects. + * + * @param workArea + */ + private void createDestinationArea(Composite workArea) { + + // project specification group + Composite projectGroup = new Composite(workArea, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 3; + layout.makeColumnsEqualWidth = false; + layout.marginWidth = 0; + projectGroup.setLayout(layout); + projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label title = new Label(projectGroup, SWT.NONE); + title + .setText(Messages.getString("ProjectMigrationWizardPage.6")); //$NON-NLS-1$ + + // project destination directory location entry field + this.directoryDestinationPathField = new Text(projectGroup, SWT.BORDER); + + this.directoryDestinationPathField.setLayoutData(new GridData( + GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); + + // browse button + browseDestinationDirectoryButton = new Button(projectGroup, SWT.PUSH); + browseDestinationDirectoryButton + .setText(Messages.getString("ProjectMigrationWizardPage.7")); //$NON-NLS-1$ + setButtonLayoutData(browseDestinationDirectoryButton); + + browseDestinationDirectoryButton + .addSelectionListener(new SelectionAdapter() { + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.events.SelectionAdapter#widgetS + * elected(org.eclipse.swt.events.SelectionEvent) + */ + public void widgetSelected(SelectionEvent e) { + handleLocationDestinationDirectoryButtonPressed(); + } + }); + + directoryDestinationPathField + .addTraverseListener(new TraverseListener() { + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.TraverseListener#keyTraversed( + * org.eclipse.swt.events.TraverseEvent) + */ + public void keyTraversed(TraverseEvent e) { + if (e.detail == SWT.TRAVERSE_RETURN) { + e.doit = false; + checkForComplete(); + } + } + + }); + + directoryDestinationPathField.addFocusListener(new FocusAdapter() { + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt + * .events.FocusEvent) + */ + public void focusLost(org.eclipse.swt.events.FocusEvent e) { + checkForComplete(); + } + + }); + + Label projectTitle = new Label(projectGroup, SWT.NONE); + projectTitle + .setText(Messages.getString("ProjectMigrationWizardPage.8")); //$NON-NLS-1$ + + // project name location entry field + this.newProjectNameField = new Text(projectGroup, SWT.BORDER); + + this.newProjectNameField.setLayoutData(new GridData( + GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); + } + + /** + * Create the area where you select the root directory for the projects. + * + * @param workArea + * Composite + */ + private void createProjectsRoot(Composite workArea) { + + // project specification group + Composite projectGroup = new Composite(workArea, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 3; + layout.makeColumnsEqualWidth = false; + layout.marginWidth = 0; + projectGroup.setLayout(layout); + projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label dirTitle = new Label(projectGroup, SWT.NONE); + dirTitle + .setText(Messages.getString("ProjectMigrationWizardPage.9")); //$NON-NLS-1$ + + // project location entry field + this.directoryPathField = new Text(projectGroup, SWT.BORDER); + + this.directoryPathField.setLayoutData(new GridData( + GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); + + // browse button + browseDirectoriesButton = new Button(projectGroup, SWT.PUSH); + browseDirectoriesButton + .setText(Messages.getString("ProjectMigrationWizardPage.10")); //$NON-NLS-1$ + setButtonLayoutData(browseDirectoriesButton); + + browseDirectoriesButton.addSelectionListener(new SelectionAdapter() { + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.events.SelectionAdapter#widgetS + * elected(org.eclipse.swt.events.SelectionEvent) + */ + public void widgetSelected(SelectionEvent e) { + handleLocationDirectoryButtonPressed(); + } + + }); + + directoryPathField.addTraverseListener(new TraverseListener() { + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.TraverseListener#keyTraversed(org.eclipse + * .swt.events.TraverseEvent) + */ + public void keyTraversed(TraverseEvent e) { + if (e.detail == SWT.TRAVERSE_RETURN) { + e.doit = false; + updateProjectsList(directoryPathField.getText().trim()); + } + } + + }); + + directoryPathField.addFocusListener(new FocusAdapter() { + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt + * .events.FocusEvent) + */ + public void focusLost(org.eclipse.swt.events.FocusEvent e) { + updateProjectsList(directoryPathField.getText().trim()); + } + + }); + } + + /* + * (non-Javadoc) Method declared on IDialogPage. Set the focus on path + * fields when page becomes visible. + */ + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible) { + this.directoryPathField.setFocus(); + } + } + + /** + * Update the list of projects based on path. Method declared public only + * for test suite. + * + * @param path + */ + public void updateProjectsList(final String path) { + // on an empty path empty selectedProjects + if (path == null || path.length() == 0) { + setMessage(Messages.getString("ProjectMigrationWizardPage.11")); //$NON-NLS-1$ + selectedProjects = new ProjectRecord[0]; + projectsList.refresh(true); + projectsList.setCheckedElements(selectedProjects); + checkForComplete(); + lastPath = path; + return; + } + + final File directory = new File(path); + long modified = directory.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() { + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.operation.IRunnableWithProgress#run(org + * .eclipse.core.runtime.IProgressMonitor) + */ + public void run(IProgressMonitor monitor) { + + boolean dirSelected = true; + + monitor + .beginTask( + Messages.getString("ProjectMigrationWizardPage.12"), //$NON-NLS-1$ + 100); + selectedProjects = new ProjectRecord[0]; + Collection files = new ArrayList(); + monitor.worked(10); + + File dirpath = new File(path); + if (dirpath.exists()) { + dirSelected = true; + } + + if (dirSelected && directory.isDirectory()) { + + if (!collectProjectFilesFromDirectory(files, directory, + null, monitor)) { + return; + } + Iterator filesIterator = files.iterator(); + selectedProjects = new ProjectRecord[files.size()]; + int index = 0; + monitor.worked(50); + monitor + .subTask(Messages.getString("ProjectMigrationWizardPage.13")); //$NON-NLS-1$ + while (filesIterator.hasNext()) { + File file = (File) filesIterator.next(); + selectedProjects[index] = new ProjectRecord(file); + index++; + } + } else { + monitor.worked(60); + } + monitor.done(); + } + + }); + } catch (InvocationTargetException e) { + IDEWorkbenchPlugin.log(e.getMessage(), e); + } catch (InterruptedException e) { + // Nothing to do if the user interrupts. + } + + projectsList.refresh(true); + projectsList.setCheckedElements(getValidProjects()); + if (getValidProjects().length < selectedProjects.length) { + setMessage( + Messages.getString("ProjectMigrationWizardPage.14"), //$NON-NLS-1$ + WARNING); + } else { + setMessage(Messages.getString("ProjectMigrationWizardPage.15")); //$NON-NLS-1$ + } + checkForComplete(); + } + + /** + * Display an error dialog with the specified message. + * + * @param message + * the error message + */ + protected void displayErrorDialog(String message) { + MessageDialog.openError(getContainer().getShell(), + getErrorDialogTitle(), message); + } + + /** + * Get the title for an error dialog. Subclasses should override. + */ + protected String getErrorDialogTitle() { + return Messages.getString("ProjectMigrationWizardPage.16"); //$NON-NLS-1$ + } + + /** + * Get the title for an error dialog. Subclasses should override. + */ + protected String getInformationDialogTitle() { + return Messages.getString("ProjectMigrationWizardPage.17"); //$NON-NLS-1$ + } + + /** + * 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 true if the operation was completed. + */ + private boolean collectProjectFilesFromDirectory(Collection files, + File directory, Set directoriesVisited, IProgressMonitor monitor) { + + if (monitor.isCanceled()) { + return false; + } + monitor + .subTask(NLS + .bind( + Messages.getString("ProjectMigrationWizardPage.18"), //$NON-NLS-1$ + directory.getPath())); + File[] contents = directory.listFiles(); + if (contents == null) + return false; + + // Initialize recursion guard for recursive symbolic links + if (directoriesVisited == null) { + directoriesVisited = new HashSet(); + try { + directoriesVisited.add(directory.getCanonicalPath()); + } catch (IOException exception) { + StatusManager.getManager().handle( + new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, + exception.getLocalizedMessage())); + } + } + + // 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; + } + } + return true; + + } + + /** + * The browse button has been selected. Select the location. + */ + protected void handleLocationDirectoryButtonPressed() { + + DirectoryDialog dialog = new DirectoryDialog(directoryPathField + .getShell()); + dialog + .setMessage(Messages.getString("ProjectMigrationWizardPage.19")); //$NON-NLS-1$ + + String dirName = directoryPathField.getText().trim(); + if (dirName.length() == 0) { + dirName = previouslyBrowsedDirectory; + } + + if (dirName.length() == 0) { + dialog.setFilterPath(IDEWorkbenchPlugin.getPluginWorkspace().getRoot() + .getLocation().toOSString()); + } else { + File path = new File(dirName); + if (path.exists()) { + dialog.setFilterPath(new Path(dirName).toOSString()); + } + } + + String selectedDirectory = dialog.open(); + if (selectedDirectory != null) { + previouslyBrowsedDirectory = selectedDirectory; + directoryPathField.setText(previouslyBrowsedDirectory); + updateProjectsList(selectedDirectory); + } + + } + + /** + * The browse button has been selected. Select the location. + */ + protected void handleLocationDestinationDirectoryButtonPressed() { + + DirectoryDialog dialog = new DirectoryDialog( + directoryDestinationPathField.getShell()); + dialog + .setMessage(Messages.getString("ProjectMigrationWizardPage.20")); //$NON-NLS-1$ + + String dirName = directoryDestinationPathField.getText().trim(); + if (dirName.length() == 0) { + dirName = previouslyBrowsedDestinationDirectory; + } + + if (dirName.length() == 0) { + dialog.setFilterPath(IDEWorkbenchPlugin.getPluginWorkspace().getRoot() + .getLocation().toOSString()); + } else { + File path = new File(dirName); + if (path.exists()) { + dialog.setFilterPath(new Path(dirName).toOSString()); + } + } + + String selectedDirectory = dialog.open(); + if (selectedDirectory != null) { + previouslyBrowsedDestinationDirectory = selectedDirectory; + directoryDestinationPathField + .setText(previouslyBrowsedDestinationDirectory); + checkForComplete(); + } + + } + + /** + * Create the selected projects + * + * @return boolean true if all project creations were + * successful. + */ + public boolean createProjects() { + //long startTime = 0; + //long estimatedTime; + + saveWidgetValues(); + final String newProjectName = newProjectNameField.getText().trim(); + final String oldLinkedPath = oldLinkedPathPrefixField.getText().trim(); + final String newLinkedPath = newLinkedPathPrefixField.getText().trim(); + + //if (showTiming) + //startTime = System.nanoTime(); + + final IPath sourcePath = new Path(directoryPathField.getText().trim()); + final IPath destinationPath = new Path(directoryDestinationPathField + .getText().trim()); + + WorkspaceModifyOperation op = new WorkspaceModifyOperation() { + protected void execute(IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException { + try { + ProjectMigrationOperation op = new ProjectMigrationOperation( sourcePath, + newProjectName, destinationPath, + oldLinkedPath, newLinkedPath); + + + monitor.beginTask("", 1); //$NON-NLS-1$ + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + op.run(new SubProgressMonitor(monitor, 1)); + + + } 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 = Messages.getString("ProjectMigrationWizardPage.21"); //$NON-NLS-1$ + IStatus status; + if (t instanceof CoreException) { + status = ((CoreException) t).getStatus(); + } else { + status = new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, 1, + message, t); + } + ErrorDialog.openError(getShell(), message, null, status); + return false; + } + return true; + } + + /** + * Performs clean-up if the user cancels the wizard without doing anything + */ + public void performCancel() { + } + + /** + * The WizardDataTransfer implementation of this + * IOverwriteQuery method asks the user whether the existing + * resource at the given path should be overwritten. + * + * @param pathString + * @return the user's reply: one of "YES", "NO", + * "ALL", or "CANCEL" + */ + 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 = NLS.bind( + Messages.getString("ProjectMigrationWizardPage.22"), //$NON-NLS-1$ + pathString); + } else { + messageString = NLS + .bind( + Messages.getString("ProjectMigrationWizardPage.23"), //$NON-NLS-1$ + path.lastSegment(), path.removeLastSegments(1) + .toOSString()); + } + + final MessageDialog dialog = new MessageDialog(getContainer() + .getShell(), Messages.getString("ProjectMigrationWizardPage.24"), null, //$NON-NLS-1$ + 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); + 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 = IDEWorkbenchPlugin.getPluginWorkspace().getRoot().getProjects(); + } + return wsProjects; + } + + /** + * Get the array of valid project records that can be imported from the + * source workspace or archive, selected by the user. If a project with the + * same name exists in both the source workspace and the current workspace, + * it will not appear in the list of projects to import and thus cannot be + * selected for import. + * + * Method declared public for test suite. + * + * @return ProjectRecord[] array of projects that can be imported into the + * workspace + */ + public ProjectRecord[] getValidProjects() { + List validProjects = new ArrayList(); + for (int i = 0; i < selectedProjects.length; i++) { + if (!isProjectInWorkspace(selectedProjects[i].getProjectName())) { + validProjects.add(selectedProjects[i]); + } + } + return (ProjectRecord[]) validProjects + .toArray(new ProjectRecord[validProjects.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.equals(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. + * + * Method declared public only for use of tests. + */ + public void restoreWidgetValues() { + IDialogSettings settings = getDialogSettings(); + if (settings != null) { + // checkbox + /*ignoreExportedIndex = settings + .getBoolean(STORE_IGNORE_EXPORTED_INDEX_ID); + ignoreExportedIndexCheckbox.setSelection(ignoreExportedIndex); + + ignoreExportedProjectRefresh = settings + .getBoolean(STORE_IGNORE_EXPORTED_PROJECT_ID); + ignoreExportedProjectRefreshCheckBox + .setSelection(ignoreExportedIndex); + + showTiming = settings.getBoolean(STORE_SHOW_TIMING_PROJECT_ID); + showTimingCheckBox.setSelection(showTiming); + */ + } + } + + /** + * 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(); + if (settings != null) { + /*settings.put(STORE_IGNORE_EXPORTED_INDEX_ID, + ignoreExportedIndexCheckbox.getSelection()); + + settings.put(STORE_IGNORE_EXPORTED_PROJECT_ID, + ignoreExportedProjectRefreshCheckBox.getSelection()); + + settings.put(STORE_SHOW_TIMING_PROJECT_ID, showTimingCheckBox + .getSelection()); + */ + } + } + + /** + * Method used for test suite. + * + * @return Button copy checkbox + */ +// public Button getIgnoreExportedIndexCheckbox() { +// return ignoreExportedIndexCheckbox; +// } +// + /** + * Method used for test suite. + * + * @return Button copy checkbox + */ +// public Button getIgnoreExportedProjectRefreshCheckbox() { +// return ignoreExportedProjectRefreshCheckBox; +// } + //// +} Index: src/org/eclipse/ui/internal/wizards/projectmigration/messages.properties =================================================================== RCS file: src/org/eclipse/ui/internal/wizards/projectmigration/messages.properties diff -N src/org/eclipse/ui/internal/wizards/projectmigration/messages.properties --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/wizards/projectmigration/messages.properties 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,52 @@ +############################################################################### +# Copyright (c) 2000, 2006 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 + +############################################################################### + +ProjectMigrationExportWizard.0=Export +ProjectMigrationExportWizardPage.1=Export Project Migration Information for use in a project migration +ProjectMigrationExportWizardPage.2=Select &projects to export: +ProjectMigrationExportWizardPage.3=&Select All +ProjectMigrationExportWizardPage.4=&Deselect All +ProjectMigrationExportWizardPage.5=Errors occurred while exporting project migration information +ProjectMigrationExportWizardPage.7=At least one project must be selected. +ProjectMigrationExportWizardPage.8=Export Project Migration Information + +ProjectMigrationExportWizardPage.0=Export Project Migration Information +ProjectMigrationExportWizardPage.6=Errors occurred while exporting project migration information +ProjectMigrationOperation.0=Creating Projects +ProjectMigrationOperation.1=Migration Interrupted +ProjectMigrationWizard_0=Migrate +ProjectMigrationWizard.0=Migrate +ProjectMigrationWizardPage.0={0} ({1}) +ProjectMigrationWizardPage.1=Project Migration +ProjectMigrationWizardPage.10=B&rowse... +ProjectMigrationWizardPage.11=Select a directory to search for existing Eclipse projects +ProjectMigrationWizardPage.12=Searching for projects +ProjectMigrationWizardPage.13=Processing results +ProjectMigrationWizardPage.14=Some projects were hidden because they exist in the workspace directory +ProjectMigrationWizardPage.15=Select a directory to search for existing Eclipse projects +ProjectMigrationWizardPage.16=Internal error +ProjectMigrationWizardPage.17=Project Migration Error +ProjectMigrationWizardPage.18=Checking: {0} +ProjectMigrationWizardPage.19=Select source directory of the project to migrate +ProjectMigrationWizardPage.2=Select a directory to search for existing Eclipse project. +ProjectMigrationWizardPage.20=Select destination directory of the migrated project +ProjectMigrationWizardPage.21=Creation Problems +ProjectMigrationWizardPage.22=''{0}'' already exists. Would you like to overwrite it? +ProjectMigrationWizardPage.23=Overwrite ''{0}'' in folder ''{1}''? +ProjectMigrationWizardPage.24=Question +ProjectMigrationWizardPage.3=&Project: +ProjectMigrationWizardPage.4=Old Linked Path Prefix: +ProjectMigrationWizardPage.5=New Linked Path Prefix: +ProjectMigrationWizardPage.6=&Destination Directory: +ProjectMigrationWizardPage.7=B&rowse... +ProjectMigrationWizardPage.8=&Destination Project Name: +ProjectMigrationWizardPage.9=Select &source directory: