### 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 @@
+ * 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.
+ *
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:///+ * 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.
+ *
+ * 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: