View | Details | Raw Unified | Return to bug 263671 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/core/resources/ResourcesPlugin.java (+9 lines)
Lines 96-101 Link Here
96
	public static final String PT_MODEL_PROVIDERS = "modelProviders"; //$NON-NLS-1$
96
	public static final String PT_MODEL_PROVIDERS = "modelProviders"; //$NON-NLS-1$
97
	
97
	
98
	/**
98
	/**
99
	 * Simple identifier constant (value <code>"migrationHelpers"</code>)
100
	 * for the migration helpers extension point.
101
	 * 
102
	 */	
103
	public static final String PT_MIGRATION_HELPERS = "migrationHelpers"; //$NON-NLS-1$
104
	
105
	/**
99
	 * Constant identifying the job family identifier for the background autobuild job.
106
	 * Constant identifying the job family identifier for the background autobuild job.
100
	 * 
107
	 * 
101
	 * @see IJobManager#join(Object, IProgressMonitor)
108
	 * @see IJobManager#join(Object, IProgressMonitor)
Lines 256-261 Link Here
256
	 */
263
	 */
257
	public static final String PREF_AUTO_REFRESH = "refresh.enabled"; //$NON-NLS-1$
264
	public static final String PREF_AUTO_REFRESH = "refresh.enabled"; //$NON-NLS-1$
258
265
266
267
259
	/**
268
	/**
260
	 * The single instance of this plug-in runtime class.
269
	 * The single instance of this plug-in runtime class.
261
	 */
270
	 */
(-)plugin.properties (+1 lines)
Lines 19-24 Link Here
19
preferencesContentTypeName = Preferences
19
preferencesContentTypeName = Preferences
20
refreshProvidersName=Refresh Providers
20
refreshProvidersName=Refresh Providers
21
modelProviders=Model Providers
21
modelProviders=Model Providers
22
migrationHelpers=Migration Helpers
22
preferencesExtPtName=Resource Preferences
23
preferencesExtPtName=Resource Preferences
23
resourceModelName=File System Resources
24
resourceModelName=File System Resources
24
25
(-)plugin.xml (+19 lines)
Lines 10-15 Link Here
10
   <extension-point id="teamHook" name="%teamHookName" schema="schema/teamHook.exsd"/>
10
   <extension-point id="teamHook" name="%teamHookName" schema="schema/teamHook.exsd"/>
11
   <extension-point id="refreshProviders" name="%refreshProvidersName" schema="schema/refreshProviders.exsd"/>
11
   <extension-point id="refreshProviders" name="%refreshProvidersName" schema="schema/refreshProviders.exsd"/>
12
   <extension-point id="modelProviders" name="%modelProviders" schema="schema/modelProviders.exsd"/>
12
   <extension-point id="modelProviders" name="%modelProviders" schema="schema/modelProviders.exsd"/>
13
   <extension-point id="migrationHelpers" name="%migrationHelpers" schema="schema/migrationHelpers.exsd"/>
13
14
14
	<extension id="preferences" point="org.eclipse.core.runtime.preferences" name="%preferencesExtPtName">
15
	<extension id="preferences" point="org.eclipse.core.runtime.preferences" name="%preferencesExtPtName">
15
		<scope name="project" class="org.eclipse.core.internal.resources.ProjectPreferences"/>
16
		<scope name="project" class="org.eclipse.core.internal.resources.ProjectPreferences"/>
Lines 188-192 Link Here
188
            properties="projectPersistentProperty"
189
            properties="projectPersistentProperty"
189
            id="org.eclipse.core.resources.mappingPropertyTester"/>
190
            id="org.eclipse.core.resources.mappingPropertyTester"/>
190
   </extension>
191
   </extension>
192
   <extension
193
         point="org.eclipse.core.filesystem.filesystems">
194
      <filesystem
195
            scheme="snapfs">
196
         <run
197
               class="org.eclipse.core.internal.resources.projectmigration.SFSFileSystem">
198
         </run>
199
      </filesystem>
200
   </extension>
201
   <extension
202
         point="org.eclipse.core.resources.migrationHelpers">
203
      <migrationHelperNatures
204
            nature="+">
205
      </migrationHelperNatures>
206
      <migrationHelperClass
207
            class="org.eclipse.core.internal.resources.projectmigration.PlatformProjectMigrationHelper">
208
      </migrationHelperClass>
209
   </extension>
191
210
192
</plugin>
211
</plugin>
(-)META-INF/MANIFEST.MF (+2 lines)
Lines 15-25 Link Here
15
 org.eclipse.core.internal.refresh;x-internal:=true,
15
 org.eclipse.core.internal.refresh;x-internal:=true,
16
 org.eclipse.core.internal.resources;x-internal:=true,
16
 org.eclipse.core.internal.resources;x-internal:=true,
17
 org.eclipse.core.internal.resources.mapping;x-internal:=true,
17
 org.eclipse.core.internal.resources.mapping;x-internal:=true,
18
 org.eclipse.core.internal.resources.projectmigration,
18
 org.eclipse.core.internal.resources.refresh.win32;x-internal:=true,
19
 org.eclipse.core.internal.resources.refresh.win32;x-internal:=true,
19
 org.eclipse.core.internal.utils;x-internal:=true,
20
 org.eclipse.core.internal.utils;x-internal:=true,
20
 org.eclipse.core.internal.watson;x-internal:=true,
21
 org.eclipse.core.internal.watson;x-internal:=true,
21
 org.eclipse.core.resources,
22
 org.eclipse.core.resources,
22
 org.eclipse.core.resources.mapping,
23
 org.eclipse.core.resources.mapping,
24
 org.eclipse.core.resources.projectmigration,
23
 org.eclipse.core.resources.refresh,
25
 org.eclipse.core.resources.refresh,
24
 org.eclipse.core.resources.team
26
 org.eclipse.core.resources.team
25
Require-Bundle: org.eclipse.ant.core;bundle-version="[3.1.0,4.0.0)";resolution:=optional,
27
Require-Bundle: org.eclipse.ant.core;bundle-version="[3.1.0,4.0.0)";resolution:=optional,
(-)schema/migrationHelpers.exsd (+138 lines)
Added Link Here
1
<?xml version='1.0' encoding='UTF-8'?>
2
<!-- Schema file written by PDE -->
3
<schema targetNamespace="org.eclipse.core.resources" xmlns="http://www.w3.org/2001/XMLSchema">
4
<annotation>
5
      <appinfo>
6
         <meta.schema plugin="org.eclipse.core.resources" id="migrationHelpers" name="%migrationHelpers"/>
7
      </appinfo>
8
      <documentation>
9
         This extension point allows contributors to assist with Project Migrations. Contributors get two chances to help. 
10
11
The first is on the export of the Project information. Contributors can create files that should be included in the zip file that is copied to the new directory. Contributors can also identify files that should be copied from the source directory to the new directory. At this stage, contributors are only called for projects with a nature that matches one in the list of natures that the contributor knows about.
12
13
The second opportunity is when the Project Migration is actually happening. The contributors are called for each file that is copied from the original source directory. The contributor can change the copied file in order to reflect the new project name or other changes.
14
15
A contributor makes a class that extends ProjectMigrationHelper.
16
      </documentation>
17
   </annotation>
18
19
   <element name="extension">
20
      <annotation>
21
         <appinfo>
22
            <meta.element />
23
         </appinfo>
24
      </annotation>
25
      <complexType>
26
         <sequence>
27
            <element ref="migrationHelperNatures" minOccurs="1" maxOccurs="unbounded"/>
28
            <element ref="migrationHelperClass"/>
29
         </sequence>
30
         <attribute name="point" type="string" use="required">
31
            <annotation>
32
               <documentation>
33
                  
34
               </documentation>
35
            </annotation>
36
         </attribute>
37
         <attribute name="id" type="string">
38
            <annotation>
39
               <documentation>
40
                  
41
               </documentation>
42
            </annotation>
43
         </attribute>
44
         <attribute name="name" type="string">
45
            <annotation>
46
               <documentation>
47
                  
48
               </documentation>
49
               <appinfo>
50
                  <meta.attribute translatable="true"/>
51
               </appinfo>
52
            </annotation>
53
         </attribute>
54
      </complexType>
55
   </element>
56
57
   <element name="migrationHelperNatures">
58
      <annotation>
59
         <documentation>
60
            These elements specify the &quot;natures&quot; that this extension knows about. Multiple natures can be specified.
61
         </documentation>
62
      </annotation>
63
      <complexType>
64
         <attribute name="nature" type="string" use="required">
65
            <annotation>
66
               <documentation>
67
                  Identifies the project nature. Projects with the specified nature can be helped by this particular migrationHelper.
68
               </documentation>
69
            </annotation>
70
         </attribute>
71
      </complexType>
72
   </element>
73
74
   <element name="migrationHelperClass">
75
      <complexType>
76
         <attribute name="class" type="string" use="required">
77
            <annotation>
78
               <documentation>
79
                  This must be a class that extends org.eclipse.core.resources.projectmigration.ProjectMigrationHelper.
80
               </documentation>
81
               <appinfo>
82
                  <meta.attribute kind="java" basedOn="org.eclipse.core.resources.projectmigration.ProjectMigrationHelper:"/>
83
               </appinfo>
84
            </annotation>
85
         </attribute>
86
      </complexType>
87
   </element>
88
89
   <annotation>
90
      <appinfo>
91
         <meta.section type="since"/>
92
      </appinfo>
93
      <documentation>
94
         3.5
95
      </documentation>
96
   </annotation>
97
98
   <annotation>
99
      <appinfo>
100
         <meta.section type="examples"/>
101
      </appinfo>
102
      <documentation>
103
         For CDT, the provided class provides the following functions:
104
105
createExportFiles(): This function exports the PDOM (much like the Team Shared Index) and identifies the &quot;.cproject&quot; file to be copied at the time of the migration.
106
107
migrateFile(): This function changes the .cproject file so that instances of the old project name are changed to the new name. A possible improvement is to use the old and new linked prefixes to make changes to the include paths specified.
108
109
The removeExportFiles() is not provide because the default implementation which just removes all files like the exported PDOM is the desired behavior.
110
111
112
      </documentation>
113
   </annotation>
114
115
   <annotation>
116
      <appinfo>
117
         <meta.section type="apiinfo"/>
118
      </appinfo>
119
      <documentation>
120
         When the Project Migration information is being exported, the function &quot;createExportFiles&quot; is called. This allows the contributor to create temporary files to be included in the migration zip file. (these files will be deleted later on by a call to &quot;removeExportFiles&quot;. For each file created, the contributor should call &quot;addExportZipFile&quot;. The contributor can override removeExportFiles if the files added via addExportZipFile should not all be deleted.
121
122
In addition to creating temporary files to be included in the migration zip file, the contributor can also indicate files to be copied from the project source directory to the migration destination directory. These files should be in the project directory. (i.e. not a file in a sub-directory.) This list of files is added through calls to &quot;addFileToMigrate&quot;.
123
124
When the Project Migration is being performed, the function &quot;migrateFile&quot; is called so the contributor has a chance to change the destination file.
125
      </documentation>
126
   </annotation>
127
128
   <annotation>
129
      <appinfo>
130
         <meta.section type="implementation"/>
131
      </appinfo>
132
      <documentation>
133
         An example of this extension is included with CDT.
134
      </documentation>
135
   </annotation>
136
137
138
</schema>
(-)src/org/eclipse/core/internal/resources/projectmigration/SFSUtilities.java (+60 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     Wind River Systems Inc.- initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.core.internal.resources.projectmigration;
12
13
import java.io.File;
14
import java.net.URI;
15
import java.net.URISyntaxException;
16
import org.eclipse.core.internal.resources.projectmigration.Messages;
17
import org.eclipse.core.resources.IProjectDescription;
18
import org.eclipse.core.resources.ResourcesPlugin;
19
import org.eclipse.core.runtime.IPath;
20
import org.eclipse.core.runtime.IProgressMonitor;
21
import org.eclipse.core.runtime.IStatus;
22
import org.eclipse.core.runtime.Status;
23
import org.eclipse.core.runtime.SubProgressMonitor;
24
25
/**
26
 * 
27
 */
28
public class SFSUtilities {
29
30
		public static void exportRefreshInfo( IProjectDescription desc, File tmpfile, IProgressMonitor monitor) {
31
			URI projectURI = desc.getLocationURI();
32
			SnapInfoStore refreshInfo = new SnapInfoStore(projectURI.getPath(),
33
				tmpfile);
34
			monitor.subTask(Messages.getString("SFSUtilities.0")); //$NON-NLS-1$
35
			refreshInfo.write(new SubProgressMonitor(monitor, 100));
36
			monitor.done();
37
		}
38
		
39
		public static void startUsingRefreshInfo( IProjectDescription description, IPath destPath, String snap_name, int numberOfLocals) {
40
			URI uri = description.getLocationURI();
41
			URI projURI = null;
42
			try {
43
				projURI = new URI(SFSFileSystem.SCHEME, uri.getAuthority(), "/", //$NON-NLS-1$
44
						destPath.toString(), snap_name);
45
			} catch (URISyntaxException e) {
46
				ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, "uri", //$NON-NLS-1$
47
						e));
48
				return;
49
			}
50
			SFSFileSystem.setRootPath(destPath.toString(),  numberOfLocals);
51
			description.setLocationURI(projURI);
52
		}
53
		public static void addRootLocalFile( String fileName ) {
54
			SFSFileSystem.setRootLocalFile( fileName );
55
		}
56
		
57
		public static void stopUsingRefreshInfo( ) {
58
			SFSFileSystem.stopUsingRefreshInfo();
59
		}
60
}
(-)src/org/eclipse/core/resources/projectmigration/ProjectMigration.java (+475 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Wind River Systems, Inc. - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.core.resources.projectmigration;
12
13
import org.eclipse.core.runtime.*;
14
15
import org.eclipse.core.runtime.IExecutableExtension;
16
17
import org.eclipse.core.internal.resources.projectmigration.Messages;
18
19
import java.io.File;
20
import java.io.FileInputStream;
21
import java.io.FileNotFoundException;
22
import java.io.FileOutputStream;
23
import java.io.InputStream;
24
import java.io.IOException;
25
import java.io.OutputStream;
26
import java.util.ArrayList;
27
import java.util.Enumeration;
28
import java.util.List;
29
import java.util.NoSuchElementException;
30
import java.util.zip.ZipEntry;
31
import java.util.zip.ZipException;
32
import java.util.zip.ZipFile;
33
import org.eclipse.core.resources.IProject;
34
import org.eclipse.core.resources.IProjectDescription;
35
import org.eclipse.core.resources.IResource;
36
import org.eclipse.core.resources.IWorkspace;
37
import org.eclipse.core.resources.ResourcesPlugin;
38
import org.eclipse.core.runtime.IPath;
39
import org.eclipse.core.runtime.IProgressMonitor;
40
import org.eclipse.core.runtime.IStatus;
41
import org.eclipse.core.runtime.NullProgressMonitor;
42
import org.eclipse.core.runtime.OperationCanceledException;
43
import org.eclipse.core.runtime.Platform;
44
import org.eclipse.core.runtime.Status;
45
import org.eclipse.core.runtime.SubProgressMonitor;
46
//import org.eclipse.core.internal.resources.projectmigration.PlatformProjectMigrationHelper;
47
import org.eclipse.core.internal.resources.projectmigration.SFSUtilities;
48
49
/**
50
 * An operation which does the actual work of migrating a project from one
51
 * directory to another.
52
 * <p>
53
 * This class may be instantiated; it is not intended to be subclassed.
54
 * </p>
55
 */
56
public class ProjectMigration    {
57
	
58
	public static final String SNAP_NAME = ".projdir.snap"; //$NON-NLS-1$
59
	public static final String MIGRATION_ZIP_NAME = ".projmig.zip"; //$NON-NLS-1$
60
61
	private IPath sourcePath;
62
63
	private IPath destinationPath;
64
65
	private String projectName;
66
	private String newProjectName;
67
68
	private String oldLinkedPathPrefix;
69
70
	private String newLinkedPathPrefix;
71
72
	/**
73
	 * Specifies a project migration that performs a "trusted import" of the
74
	 * specified project from the source directory to the destination directory.
75
	 * This means that the file refresh information and other files from the source
76
	 * project are to be imported and trusted, i.e., not verified.
77
	 * <p>
78
	 * The <code>sourcePath</code> parameter represents the directory containing
79
	 * the project to import.
80
	 * </p>
81
	 *  
82
	 * @param destinationPath
83
	 *            full path of destination directory
84
	 * @param sourcePath
85
	 *            full path of source directory, containing a project
86
	 * @param newName
87
	 *            new name of project (empty if no rename)
88
	 */
89
	public ProjectMigration( IPath sourcePath, String newName, IPath destinationPath){
90
		super();
91
		this.projectName = "uninitialized_project_name"; //$NON-NLS-1$
92
93
		this.sourcePath = sourcePath;
94
		this.destinationPath = destinationPath;
95
		this.newProjectName = newName;
96
		this.oldLinkedPathPrefix = ""; //$NON-NLS-1$
97
		this.newLinkedPathPrefix = ""; //$NON-NLS-1$
98
	}
99
100
	/**
101
	 * Sets the linked directory path prefix.
102
	 * 
103
	 * @param oldLinkedPathPrefix
104
	 *            linked to the old directory path prefix
105
	 * @param newLinkedPathPrefix
106
	 *            linked to the new directory path prefix
107
	 */
108
	public void setLinkedPathPrefix(String oldLinkedPathPrefix, String newLinkedPathPrefix) {
109
		this.oldLinkedPathPrefix = oldLinkedPathPrefix;
110
		this.newLinkedPathPrefix = newLinkedPathPrefix;
111
	}
112
113
114
	/*
115
	 * Method declared on WorkbenchModifyOperation. Imports the specified
116
	 * project from the file system.
117
	 * 
118
	 * @param progressMonitor IProgressMonitor object
119
	 */
120
	public void execute(IProgressMonitor progressMonitor) throws Exception {
121
		/* TODO: remove this?
122
		 * Check the cdt debug activity settings. If on, print a message to
123
		 * stdout announcing that the Project migration is starting. This makes
124
		 * timing the migration easier. Please note that the hard-coded
125
		 * references to the plugin and activity names is a bit of a kludge. It
126
		 * would not be needed if the project migration API were actually part
127
		 * of CDT instead of in a separate plugin.
128
		 */
129
		String option = "org.eclipse.cdt.core/debug/indexer/activity"; //$NON-NLS-1$
130
		String trace = Platform.getDebugOption(option);
131
		boolean internallyActivated = Boolean.getBoolean(option);
132
		boolean showActivity = internallyActivated || (trace != null && trace.equalsIgnoreCase("true")); //$NON-NLS-1$
133
		if (showActivity == true) {
134
			System.out.println(Messages.getString("ProjectMigration.0")); //$NON-NLS-1$
135
		}
136
		IProgressMonitor monitor = progressMonitor;
137
		if( monitor == null ) {
138
			monitor = new NullProgressMonitor();
139
		}
140
		monitor.beginTask("", 100 ); //$NON-NLS-1$
141
		if (sourcePath.equals(destinationPath)) {
142
			throw new Exception(Messages.getString("ProjectMigration.1")); //$NON-NLS-1$
143
		}
144
		try {
145
			{
146
				IPath path  = sourcePath.append(IProjectDescription.DESCRIPTION_FILE_NAME);
147
				final IWorkspace workspace = ResourcesPlugin.getWorkspace();
148
				IProjectDescription description = workspace.loadProjectDescription(path);
149
				this.projectName = description.getName();
150
			}
151
			extractMigrationFiles(sourcePath, destinationPath);
152
			
153
			File[] projectFiles = getProjectFiles(sourcePath);
154
			if (projectFiles.length == 0) {
155
				throw new Exception(Messages.getString("ProjectMigration.2")); //$NON-NLS-1$
156
			}
157
			int i = 0;
158
159
			for (i = 0; i < projectFiles.length; i++) {
160
				File file = projectFiles[i];
161
				if (file != null) {
162
					if (!copyRecursively(file, destinationPath, new SubProgressMonitor( monitor, 20/projectFiles.length))) {
163
						throw new Exception(Messages.getString("ProjectMigration.4")); //$NON-NLS-1$
164
					}
165
				}
166
			}
167
168
			IPath path = destinationPath;
169
			
170
			/*
171
			 * Let the project migration helpers have a chance at changing the copied files.
172
			 */
173
			changeCopiedFiles( projectFiles, new SubProgressMonitor( monitor, 20 ) );
174
			
175
//	PlatformProjectMigrationHelper projFile = new PlatformProjectMigrationHelper(path, projectFiles, newProjectName, oldLinkedPathPrefix, newLinkedPathPrefix);
176
	
177
//			projFile.performProjectRenaming(new SubProgressMonitor(monitor,20));
178
	
179
			path = destinationPath.append(IProjectDescription.DESCRIPTION_FILE_NAME);
180
	
181
			final IWorkspace workspace = ResourcesPlugin.getWorkspace();
182
			IProjectDescription description = workspace.loadProjectDescription(path);
183
			String projName = description.getName();
184
			final IProject project = workspace.getRoot().getProject(projName);
185
	
186
			File importFile = destinationPath.append(ProjectMigration.SNAP_NAME).toFile();
187
			if (importFile.exists()) {
188
				SFSUtilities.startUsingRefreshInfo(description, destinationPath, ProjectMigration.SNAP_NAME, projectFiles.length);
189
				for(  i = 0; i < projectFiles.length; i++ ) {
190
					SFSUtilities.addRootLocalFile(projectFiles[i].getName()); 
191
				}
192
			}
193
	
194
			project.create(description, new SubProgressMonitor( monitor, 10 ));
195
	
196
			// open the project and perform the refresh before returning
197
			project.open(IResource.NONE, new SubProgressMonitor( monitor, 40 ) );
198
		}
199
		finally {
200
			// now turn off the use of the snapshot file, if active
201
			SFSUtilities.stopUsingRefreshInfo();
202
		}
203
		monitor.done();
204
	}
205
	
206
	private void changeCopiedFiles(File[] projectFiles, IProgressMonitor monitor) {
207
		IExecutableExtension[] extensions = getMigrationHelpers();
208
		if( extensions.length == 0 ) {
209
			monitor.done();
210
			return;
211
		}			
212
		for( int i = 0; i < projectFiles.length; i++ ) {
213
214
			/*
215
			 * Ask the helpers to migrate files that are copied.
216
			 */
217
218
			for( int j = 0; j < extensions.length; j ++ ) {
219
				if (extensions[j] instanceof ProjectMigrationHelper) {
220
					ProjectMigrationHelper helper = (ProjectMigrationHelper) extensions[j];
221
					IPath filePath = destinationPath.append( projectFiles[i].getName());
222
					helper.migrateFile( filePath, projectName, newProjectName, oldLinkedPathPrefix, newLinkedPathPrefix);
223
				}
224
			}
225
			monitor.worked(1);
226
		}
227
	}
228
229
	/*
230
	 * Get the set of migration helpers. We don't match on the natures since no
231
	 * projects are actually open. Instead, the migration helper must "know" which
232
	 * files it can help migrate.
233
	 */
234
	private IExecutableExtension[] getMigrationHelpers() {
235
		List helpers = new ArrayList();
236
237
		try {
238
	        IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_MIGRATION_HELPERS);
239
			if (extension != null) {
240
				IExtension[] extensions = extension.getExtensions();
241
				for (int i = 0; i < extensions.length; i++ ) {
242
					IExtension extension2 = extensions[i]; 
243
					IConfigurationElement[] configElements = extension2.getConfigurationElements();
244
					for ( int j = 0; j < configElements.length; j ++ ) {
245
						IConfigurationElement configElement = configElements[j];
246
						if( configElement.getAttribute( "class" ) != null ) { //$NON-NLS-1$
247
							helpers.add( configElement.createExecutableExtension("class")); //$NON-NLS-1$
248
						}
249
					}
250
				}
251
			}
252
		} catch (CoreException e) {
253
			ResourcesPlugin.getPlugin().getLog().log(new Status( IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, Messages.getString("ExportProjectMigrationInfo.4"), e));  //$NON-NLS-1$
254
		}
255
		
256
		return (IExecutableExtension[]) helpers.toArray(new IExecutableExtension[0]);
257
			
258
	}
259
	
260
		private void readEntry(ZipFile zip, ZipEntry entry, File tmpFile)
261
				throws IOException {
262
			InputStream stream = zip.getInputStream(entry);
263
			OutputStream outEntry = new FileOutputStream(tmpFile);
264
			try {
265
				byte[] buffer = new byte[2048];
266
				int read;
267
				while ((read = stream.read(buffer)) >= 0) {
268
					outEntry.write(buffer, 0, read);
269
				}
270
			} finally {
271
				close(outEntry);
272
			}
273
		}
274
275
		private void close(OutputStream out) {
276
			try {
277
				if (out != null) {
278
					out.close();
279
				}
280
			} catch (IOException e) {
281
				ResourcesPlugin.getPlugin().getLog().log( new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.2"), e)); //$NON-NLS-1$
282
283
			}
284
		}
285
286
287
288
	/**
289
	 * Copies the specified file system object recursively into the destination
290
	 * If the import fails, adds a status object to the list to be returned by
291
	 * <code>getStatus</code>.
292
	 * 
293
	 * @param file
294
	 *            the file system object to be imported
295
	 * @exception OperationCanceledException
296
	 *                if canceled
297
	 */
298
	private boolean copyRecursively(File file, IPath destPath, IProgressMonitor monitor) {
299
		if (monitor.isCanceled()) {
300
			throw new OperationCanceledException();
301
		}
302
		if (!file.isDirectory()) {
303
			return copyFile(file, destPath, monitor);
304
		}
305
306
		IPath folderPath = destPath.addTrailingSeparator();
307
		folderPath = folderPath.append(file.getName());
308
		boolean success = new File(folderPath.toOSString()).mkdir();
309
		if (!success) {
310
			monitor.done();
311
			return false;
312
		}
313
		File[] contents = file.listFiles();
314
		monitor.beginTask("", contents.length); //$NON-NLS-1$
315
		for (int i = 0; i < contents.length; i++) {
316
			if (!copyRecursively(contents[i], folderPath, new SubProgressMonitor( monitor, 1 ) )) {
317
				monitor.done();
318
				return false;
319
			}
320
		}
321
		monitor.done();
322
		return true;
323
	}
324
325
	/**
326
	 * Copies the specified file system object into the destination. If the copy
327
	 * fails, returns false.
328
	 */
329
	private boolean copyFile(File file, IPath dPath, IProgressMonitor monitor) {
330
331
		String filePath = file.getAbsolutePath();
332
		monitor.subTask(filePath);
333
334
		// assume that the source and target are not the same
335
		try {
336
			FileInputStream from = null;
337
			try {
338
				from = new FileInputStream(file);
339
			} catch (FileNotFoundException e) {
340
				// file was not found. null case is handled.
341
			}
342
			if (from == null) {
343
				monitor.done();
344
				return false;
345
			}
346
			IPath destPath = dPath.addTrailingSeparator();
347
			destPath = destPath.append(file.getName());
348
			FileOutputStream to = null;
349
			try {
350
				to = new FileOutputStream(destPath.toString());
351
			} catch (FileNotFoundException e) {
352
				from.close();
353
				monitor.done();
354
				return false;
355
			}
356
			try {
357
				byte[] buffer = new byte[4096];
358
				int bytesRead;
359
360
				while ((bytesRead = from.read(buffer)) != -1)
361
					to.write(buffer, 0, bytesRead); // write
362
			} finally {
363
				try {
364
					from.close();
365
				} catch (IOException e) {
366
					ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.6"), e)); //$NON-NLS-1$
367
368
				}
369
370
				try {
371
					to.close();
372
				} catch (IOException e) {
373
					ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.7"), e)); //$NON-NLS-1$
374
375
				}
376
			}
377
			monitor.done();
378
			return true;
379
		} catch (IOException e) {
380
			monitor.done();
381
			return false;
382
		}
383
	}
384
385
	/**
386
	 * Get the list of files that need to be copied from this directory. This
387
	 * includes  any 0-length entries in the zip file. The 0-length
388
	 * entries are used to capture the names of files that the migration helper
389
	 * extensions wanted to have copied.
390
	 */
391
	private File[] getProjectFiles(IPath importSourcePath) {
392
		
393
		/*
394
		 * Look for the Migration zip file
395
		 */
396
		File zipFile = importSourcePath.append(ProjectMigration.MIGRATION_ZIP_NAME).toFile();
397
		if( !zipFile.exists() ) {
398
			return new File[0];
399
		}
400
401
		/*
402
		 * Open the zip file and get the list of names for the entries that are 0 length. This
403
		 * should be a list of files to copy. Verify that the names are in the contents.
404
		 */
405
		List files = new ArrayList();
406
		try {
407
			ZipFile zip = new ZipFile(zipFile);
408
			Enumeration zipEntriesList = zip.entries();
409
			try {
410
				while (true) {
411
					ZipEntry entry;
412
					entry = (ZipEntry) zipEntriesList.nextElement();
413
					if (entry.getSize() == 0) {
414
						File entryFile = importSourcePath.append(entry.getName()).toFile();
415
						if( entryFile.exists() ) {
416
							files.add( entryFile );
417
						}
418
					}
419
				}
420
			} catch (NoSuchElementException e) {
421
				// done with all entries
422
			} finally {
423
				zip.close();
424
			}
425
		} catch (ZipException e) {
426
			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.8"), e)); //$NON-NLS-1$
427
		} catch (IOException e) {
428
			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.9"), e)); //$NON-NLS-1$
429
430
		}
431
432
		return (File[]) files.toArray(new File[0]);
433
	}
434
	/**
435
	 * Extract all non-zero length files from the zip file into the destination directory.
436
	 */
437
	private void extractMigrationFiles(IPath importSourcePath, IPath dPath) {
438
		
439
		/*
440
		 * Look for the Migration zip file
441
		 */
442
		File zipFile = importSourcePath.append(ProjectMigration.MIGRATION_ZIP_NAME).toFile();
443
		if( !zipFile.exists() ) {
444
			return;
445
		}
446
		
447
		try {
448
			ZipFile zip = new ZipFile(zipFile);
449
			Enumeration zipEntriesList = zip.entries();
450
			try {
451
				while (true) {
452
					ZipEntry entry;
453
					entry = (ZipEntry) zipEntriesList.nextElement();
454
					if (entry.getSize() != 0 /*&& entry.getName().equals(ProjectMigration.SNAP_NAME)*/) {
455
						File tmpFile = dPath.append(entry.getName()).toFile();
456
						readEntry( zip, entry, tmpFile);
457
					}
458
				}
459
			} catch (NoSuchElementException e) {
460
				// done with all entries
461
			} finally {
462
				zip.close();
463
			}
464
		} catch (ZipException e) {
465
			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.8"), e)); //$NON-NLS-1$
466
		} catch (IOException e) {
467
			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.9"), e)); //$NON-NLS-1$
468
469
		}
470
471
		return ;
472
	}
473
474
475
}
(-)src/org/eclipse/core/resources/projectmigration/ProjectMigrationHelper.java (+262 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.core.resources.projectmigration;
12
13
import java.io.FileInputStream;
14
import java.io.FileOutputStream;
15
16
import java.io.File;
17
import java.util.ArrayList;
18
import java.util.List;
19
import org.eclipse.core.resources.IProject;
20
import org.eclipse.core.runtime.CoreException;
21
import org.eclipse.core.runtime.IConfigurationElement;
22
import org.eclipse.core.runtime.IExecutableExtension;
23
import org.eclipse.core.runtime.IPath;
24
import org.eclipse.core.runtime.IProgressMonitor;
25
26
/**
27
 * This is the base class for ProjectMigration Extensions.
28
 * The extension has two parts to contribute:
29
 * 
30
 *  1. At the time of Export, the extension can:
31
 *  	- create files that will be included in the zip file
32
 *  		created as the output of the export.
33
 *  	- specify files that should be copied from the source
34
 *  		project directory to the new project directory.
35
 *     When the export is called, the createExportFiles() is called.
36
 *     This function can create files as needed and then make calls to
37
 *     addExportZipFile() and addFilesToMigrate() to specify files to
38
 *     include in the zip file and files to be copied respectively.
39
 *     
40
 *     After the zip file is created, a call is made to removeExportFiles()
41
 *     to remove the files that were added to the zip file. The assumption is 
42
 *     that they were all temporary files. If this assumption is not true, then
43
 *     override the removeExportFiles() and do your own thing.
44
 *     
45
 *     At the time of the export, the extension only comes into play if the
46
 *     "nature" specified with the extension matches one of the natures in the project.
47
 *     
48
 *  2. At the time of the migration, the extension can offer assistance with changing
49
 *  	any files that are copied over from the source project to the destination project.
50
 *  	This is done through calls to migrateFile(). This function is called for each file.
51
 *  	The extension can change the contents as needed. Typically, the project name is
52
 *  	changed so references to the old name must be changed to the new name.
53
 *  
54
 *     At the time of the migration, all extensions are called, regardless of the nature.
55
 *     The extension will need to look at the name of the file and if the file is not
56
 *     special to the extension, then it should not do anything to the file.
57
 */
58
public class ProjectMigrationHelper implements IExecutableExtension {
59
60
	/*
61
	 * This is the project that this instance is for. This field is only
62
	 * populated for the export operation. It is not populated at the time
63
	 * of the migration.
64
	 */
65
	private IProject fProject;
66
	
67
	/*
68
	 * This local class contains the file and entry name for a file that should be
69
	 * added to the zip file.
70
	 */
71
	public class ExportZipFileEntryInfo {
72
		private File fFile;
73
		private String fName;
74
		public ExportZipFileEntryInfo( File file, String name ) {
75
			fFile = file;
76
			fName = name;
77
		}
78
		public File getFile() {
79
			return fFile;
80
		}
81
		public String getName() {
82
			return fName;
83
		}
84
	}
85
	
86
	/*
87
	 * This is the list of files to be added to the zip file. Each entry
88
	 * is an ExportZipFileEntryInfo object.
89
	 */
90
	public List fExportZipFiles = new ArrayList();
91
92
	/*
93
	 * This is the list of files to be copied at the time of the migration.
94
	 * Each entry is a String. You can really only copy files or directories that are in
95
	 * the root of the project directory. 
96
	 */
97
	private List fFilesToMigrate = new ArrayList();
98
	
99
	/*
100
	 * Public Methods
101
	 */
102
	
103
	/*
104
	 * Plain constructor. Extensions must have one of these.
105
	 */
106
	public ProjectMigrationHelper() {
107
		return;
108
	}
109
	
110
111
	/**
112
	 * This function should create any files that should be included in
113
	 * the zip file representing the exported migration information.
114
	 * 
115
	 * The function should create the files and make a call to addExportZipFile()
116
	 * for each file created.
117
	 * 
118
	 * Files that should be copied at the time of the migration (but 
119
	 * not included in the zip file) should be added through calls to addFileToMigrate()
120
	 * 
121
	 * @param monitor - progress monitor for this function.
122
	 * @throws CoreException
123
	 */
124
	public void createExportFiles(IProgressMonitor monitor) throws CoreException {
125
		/*
126
		 * This function should be in the sub-class if there really are files
127
		 * that need to be copied and migrated.
128
		 */
129
	}
130
131
	/*
132
	 * This function removes files created by createExportFiles().
133
	 * It is assumed that all files created are temporary files and should be
134
	 * deleted. If this is the case, then this default implementation is sufficient.
135
	 * If this is not the case, then the extension should override this function
136
	 * and determine the proper disposal of the files created in createExportFiles.
137
	 */
138
	public void removeExportFiles() {
139
		for( int i = 0; i < fExportZipFiles.size(); i++) {
140
			ExportZipFileEntryInfo exportFile = (ExportZipFileEntryInfo) fExportZipFiles.get(i);
141
			File file = exportFile.getFile();
142
			file.delete();
143
		}
144
		fExportZipFiles = null;
145
	}
146
	/**
147
	 * This function is called for each file that is copied from the source project directory. The Extension
148
	 * has an opportunity to change the contents of the file.
149
	 * 
150
	 * The function is called after the file has been copied. The extension should only change the destination
151
	 * file. (filePath)
152
153
	 * @param filePath - path of the copied file
154
	 * @param oldname - name of the original project
155
	 * @param newname - name of the migrated project
156
	 * @param fromLinked - A prefix for linked folders or other paths
157
	 * @param toLinked - What the fromLinked prefix should be changed to
158
	 * @return true if file is modified, else return false.
159
	 */
160
	public boolean migrateFile( IPath filePath, String oldname, String newname, String fromLinked, String toLinked ) {
161
		return false;
162
	}
163
	
164
165
	/* (non-Javadoc)
166
	 * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
167
	 * 
168
	 * 
169
	 * Override this function if you have added other extension elements and want to do something with that data.
170
	 */
171
172
	/**
173
	 * @throws CoreException  
174
	 */
175
	public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
176
		/*
177
		 * This function will get any properties and values associated with the extension point. 
178
		 * The sub-class should have its own version if it wants to save the properties and do something
179
		 * with them.
180
		 */
181
182
	}
183
	
184
185
	/**
186
	 * Set the project that this extension is associated with. 
187
	 * This will be null during the actual migration itself since
188
	 * neither the source nor the destination projects are actually
189
	 * open.
190
	 * 
191
	 * @param project
192
	 */
193
	public final void setProject( IProject project ) {
194
		fProject = project;
195
	}
196
	
197
	/*
198
	 * Return the project (could be null) associated with this extension.
199
	 */
200
	public final IProject getProject( ) {
201
		return fProject;
202
	}
203
	
204
	
205
	public final void addExportZipFile( File file, String entryName ) {
206
		ExportZipFileEntryInfo info = new ExportZipFileEntryInfo( file, entryName );
207
		fExportZipFiles.add( info );
208
	}
209
	
210
211
	
212
	public final List getExportZipFiles() {
213
		return fExportZipFiles;
214
	}
215
	
216
	public final List getFilesToMigrate() {
217
		return fFilesToMigrate;
218
	}
219
	
220
	public void addFileToMigrate(String name) {
221
		fFilesToMigrate.add(name);
222
	}
223
	
224
	/*
225
	 * Utility Functions
226
	 */
227
	
228
	/**
229
	 * Read a file into a String class.
230
	 * 
231
	 * @param filepath
232
	 *            path to the file to read *@return file contents as a string
233
	 */
234
	public String readFileIntoString(String filepath) throws Exception {
235
		FileInputStream fis = new FileInputStream(filepath);
236
		int x = fis.available();
237
		byte b[] = new byte[x];
238
239
		fis.read(b);
240
		fis.close();
241
242
		return new String(b);
243
	}
244
245
	/**
246
	 * Write the string to a file.
247
	 * 
248
	 * @param filepath
249
	 *            path to the file to write to
250
	 * @param data
251
	 *            string containing the data to write
252
	 */
253
	public void writeStringIntoFile(String filepath, String data)
254
			throws Exception {
255
		FileOutputStream fos = new FileOutputStream(filepath);
256
		byte b[] = data.getBytes();
257
258
		fos.write(b);
259
		fos.close();
260
	}
261
262
}
(-)src/org/eclipse/core/internal/resources/projectmigration/SnapInfo.java (+94 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006, 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Wind River Systems, Inc. - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.core.internal.resources.projectmigration;
12
13
import org.eclipse.core.filesystem.EFS;
14
import org.eclipse.core.filesystem.provider.FileInfo;
15
16
public class SnapInfo extends FileInfo {
17
18
	// same as FileInfo.ATTRIBUTE_DRECTORY which is unfortunately private
19
	static int ATTRIBUTE_DIRECTORY = 1 << 0;
20
21
	int nextIndex;
22
	int parentIndex;
23
	int childIndex;
24
25
	public SnapInfo(String name) {
26
		super(name);
27
		nextIndex = 0;
28
		parentIndex = 0;
29
		childIndex = 0;
30
	}
31
32
	public void setAttributes(int attributes) {
33
		if ((attributes & EFS.ATTRIBUTE_READ_ONLY) != 0) {
34
			setAttribute(EFS.ATTRIBUTE_READ_ONLY, true);
35
		}
36
		if ((attributes & EFS.ATTRIBUTE_EXECUTABLE) != 0) {
37
			setAttribute(EFS.ATTRIBUTE_EXECUTABLE, true);
38
		}
39
		if ((attributes & EFS.ATTRIBUTE_ARCHIVE) != 0) {
40
			setAttribute(EFS.ATTRIBUTE_ARCHIVE, true);
41
		}
42
		if ((attributes & EFS.ATTRIBUTE_HIDDEN) != 0) {
43
			setAttribute(EFS.ATTRIBUTE_HIDDEN, true);
44
		}
45
		if ((attributes & ATTRIBUTE_DIRECTORY) != 0) {
46
			setDirectory(true);
47
		}
48
	}
49
50
	//@Override
51
	public boolean exists() {
52
		return true; // we always act as if the file exists
53
	}
54
55
	//@Override
56
	public void setExists(boolean value) {
57
		// ignore attempts to change this
58
	}
59
60
	//@Override
61
	public String getStringAttribute(int attribute) {
62
		// all symbolic links are resolved in the snapshot
63
		return null;
64
	}
65
66
	//@Override
67
	public void setStringAttribute(int attribute, String value) {
68
		// ignore attempts to change this
69
	}
70
71
	public int getNextIndex() {
72
		return nextIndex;
73
	}
74
75
	public void setNextIndex(int x) {
76
		nextIndex = x;
77
	}
78
79
	public int getParentIndex() {
80
		return parentIndex;
81
	}
82
83
	public void setParentIndex(int x) {
84
		parentIndex = x;
85
	}
86
87
	public int getChildIndex() {
88
		return childIndex;
89
	}
90
91
	public void setChildIndex(int x) {
92
		childIndex = x;
93
	}
94
}
(-)src/org/eclipse/core/internal/resources/projectmigration/Messages.java (+37 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.core.internal.resources.projectmigration;
12
13
import java.util.MissingResourceException;
14
import java.util.ResourceBundle;
15
16
/**
17
 * 
18
 */
19
public class Messages {
20
	private static final String BUNDLE_NAME = "org.eclipse.core.internal.resources.projectmigration.messages"; //$NON-NLS-1$
21
22
	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
23
24
	private Messages() {
25
		/*
26
		 * no initialization needed
27
		 */
28
	}
29
30
	public static String getString(String key) {
31
		try {
32
			return RESOURCE_BUNDLE.getString(key);
33
		} catch (MissingResourceException e) {
34
			return '!' + key + '!';
35
		}
36
	}
37
}
(-)src/org/eclipse/core/internal/resources/projectmigration/messages.properties (+20 lines)
Added Link Here
1
ExportProjectMigrationInfo.0=Error creating temporary file
2
ExportProjectMigrationInfo.1=Error closing input stream
3
ExportProjectMigrationInfo.2=Error closing output stream
4
ExportProjectMigrationInfo.3=Error writing entries to zip file
5
ExportProjectMigrationInfo.4=Exception received trying to get extensions
6
ExportProjectMigrationInfo.5=Preparing Files
7
ExportProjectMigrationInfo.6=Storing Files
8
9
PlatformProjectMigrationHelper.0=Exception trying to migrate file: 
10
ProjectMigration.0=Starting Project Migration.
11
ProjectMigration.1=Destination same as source directory
12
ProjectMigration.2=No project files present
13
ProjectMigration.3=No files other than project files found
14
ProjectMigration.4=Error copying .project, etc.
15
ProjectMigration.5=Error closing the zip file
16
ProjectMigration.6=Error closing file
17
ProjectMigration.7=Error closing file
18
ProjectMigration.8=Error accessing migration Zipfile
19
ProjectMigration.9=I/O Error accessing migration Zipfile
20
SFSUtilities.0=Writing Project Migration Information
(-)src/org/eclipse/core/internal/resources/projectmigration/PlatformProjectMigrationHelper.java (+385 lines)
Added Link Here
1
2
/*******************************************************************************
3
 * Copyright (c) 2000, 2006, 2008 IBM Corporation and others.
4
 * All rights reserved. This program and the accompanying materials
5
 * are made available under the terms of the Eclipse Public License v1.0
6
 * which accompanies this distribution, and is available at
7
 * http://www.eclipse.org/legal/epl-v10.html
8
 *
9
 * Contributors:
10
 *     Wind River Systems, Inc. - initial API and implementation
11
 *******************************************************************************/
12
package org.eclipse.core.internal.resources.projectmigration;
13
14
15
16
import org.eclipse.core.runtime.Status;
17
18
import org.eclipse.core.runtime.IStatus;
19
20
import org.eclipse.core.runtime.CoreException;
21
22
23
24
import org.eclipse.core.runtime.IProgressMonitor;
25
26
import javax.xml.transform.OutputKeys;
27
28
import javax.xml.transform.Transformer;
29
30
import javax.xml.transform.TransformerFactory;
31
32
import javax.xml.transform.stream.StreamResult;
33
34
import javax.xml.transform.dom.DOMSource;
35
36
import java.io.File;
37
38
39
import javax.xml.parsers.DocumentBuilder;
40
import javax.xml.parsers.DocumentBuilderFactory;
41
import org.eclipse.core.resources.IProjectDescription;
42
import org.eclipse.core.resources.projectmigration.ProjectMigrationHelper;
43
import org.eclipse.core.resources.ResourcesPlugin;
44
45
46
import org.eclipse.core.runtime.IPath;
47
48
49
import org.w3c.dom.Document;
50
import org.w3c.dom.Element;
51
import org.w3c.dom.Node;
52
import org.w3c.dom.NodeList;
53
54
/**
55
 * An operation which does the actual work of renaming the project name in the
56
 * .project file and using extension points to modify other files.
57
 * <p>
58
 * This class may be instantiated; it is not intended to be subclassed.
59
 * </p>
60
 */
61
/*
62
 * public class ProjectMigrationExtension extends ProjectMigrationHelper {
63
64
	
65
	@Override
66
	
67
	private void checkMonitor(IProgressMonitor monitor) {
68
		if (monitor.isCanceled()) {
69
			throw new OperationCanceledException();
70
		}
71
	}
72
73
	@ Override
74
	public boolean migrateFile( IPath filePath, String oldname, String newname, String fromLinked, String toLinked ) {
75
		if( filePath.toFile().getName().equals(".cproject") )  { //$NON-NLS-1$
76
			
77
			try {
78
				// process the .cproject file
79
				String data = readFileIntoString(filePath.toString());
80
			
81
				String new_data = data
82
						.replaceAll("\\b" + oldname + "\\b", newname); //$NON-NLS-1$ //$NON-NLS-2$
83
				if (!data.equals(new_data)) {
84
					writeStringIntoFile(filePath.toString(), new_data);
85
				}
86
			} catch (Exception e) {
87
				CCorePlugin.log( Messages.ProjectMigrationExtension_2, e );
88
			}
89
		}
90
		return true;
91
	}
92
}
93
*/
94
public class PlatformProjectMigrationHelper extends ProjectMigrationHelper {
95
96
97
	public PlatformProjectMigrationHelper() {
98
		super();
99
	}
100
	/**
101
	 * @throws CoreException  
102
	 */
103
	public void createExportFiles(IProgressMonitor monitor) throws CoreException {
104
		monitor.beginTask("", 100); //$NON-NLS-1$
105
		
106
		addFileToMigrate( IProjectDescription.DESCRIPTION_FILE_NAME );
107
		monitor.done();
108
	
109
	}
110
	/**
111
	 * Specifies a project rename operation. This means that the project name in
112
	 * the .project files are renamed.
113
	 */
114
	/*
115
	public PlatformProjectMigrationHelper(IPath path, File[] projFiles, String newProjectName,
116
			String oldLinkPathPrefix, String newLinkPathPrefix) {
117
		projectPath = path;
118
		IPath projPath = path;
119
120
		projectFiles = projFiles;
121
		projPath = projPath.addTrailingSeparator();
122
		projPath = projPath.append(IProjectDescription.DESCRIPTION_FILE_NAME);
123
		this.projectFile = projPath.toString();
124
125
		this.newProjectName = newProjectName;
126
		this.oldLinkPathPrefix = oldLinkPathPrefix;
127
		this.newLinkPathPrefix = newLinkPathPrefix;
128
		this.modified = false;
129
	}
130
	*/
131
	public boolean migrateFile( IPath filePath, String oldname, String newname, String fromLinked, String toLinked ) {
132
		if( filePath.toFile().getName().equals(IProjectDescription.DESCRIPTION_FILE_NAME) )  {
133
			
134
			try {
135
				Document dom = parseProjectFile(filePath);
136
				if ( processLinkedResources(dom, fromLinked, toLinked) == true ) {
137
					saveProjectFile(filePath, dom);
138
				}
139
				// process the .project file
140
				String data = readFileIntoString(filePath.toString());
141
			
142
				String new_data = data
143
						.replaceAll("\\b" + oldname + "\\b", newname); //$NON-NLS-1$ //$NON-NLS-2$
144
				if (!data.equals(new_data)) {
145
					writeStringIntoFile(filePath.toString(), new_data);
146
				}
147
			} catch (Exception e) {
148
				ResourcesPlugin.getPlugin().getLog().log( new Status( IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, Messages.getString("PlatformProjectMigrationHelper.0") + filePath.toString(), e) ); //$NON-NLS-1$
149
			}
150
		}
151
		return true;
152
	}
153
154
155
	/**
156
	 * Parse the xml project files.
157
	 * 
158
	 * @return true if successful otherwise false
159
	 */
160
	private Document parseProjectFile(IPath filePath) throws Exception {
161
		// get the factory
162
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
163
164
		// Using factory get an instance of document builder
165
		DocumentBuilder db = dbf.newDocumentBuilder();
166
167
		// parse using builder to get DOM representation of the XML file
168
		return db.parse(filePath.toFile());
169
170
	}
171
172
	/**
173
	 * Process the linked resource directories that is in the .project file.
174
	 * 
175
	 * @param oldPath
176
	 *            prefix to the old path
177
	 * @param newPath
178
	 *            prefix to the new path
179
	 */
180
	private boolean processLinkedResources(Document dom, String oldPath, String newPath) {
181
		// get the root element
182
		
183
		Element docEle = dom.getDocumentElement();
184
		boolean changed = false;
185
186
		Node last = docEle.getLastChild();
187
		Node curr = docEle.getFirstChild(); // get the root element
188
		boolean found = false;
189
190
		while (curr != last) {
191
			if (curr.getNodeName().equals("linkedResources")) { //$NON-NLS-1$
192
				found = true;
193
				break;
194
			}
195
			curr = curr.getNextSibling();
196
		}
197
198
		if (!found)
199
			return changed;
200
201
		// get the root element
202
		NodeList listOfLinkedResources = curr.getChildNodes();
203
		if (listOfLinkedResources == null)
204
			return changed;
205
206
		int totalResources = listOfLinkedResources.getLength();
207
208
		for (int s = 0; s < totalResources; s++) {
209
210
			Node linkLinkedResourcesNode = listOfLinkedResources.item(s);
211
			if (linkLinkedResourcesNode.getNodeType() == Node.ELEMENT_NODE) {
212
213
				Element linkLinkedResourcesElement = (Element) linkLinkedResourcesNode;
214
215
				// -------
216
				NodeList locationNameList = linkLinkedResourcesElement
217
						.getElementsByTagName("location"); //$NON-NLS-1$
218
				if (locationNameList == null)
219
					return changed;
220
221
				Element locationNameElement = (Element) locationNameList
222
						.item(0);
223
224
				NodeList textFNList = locationNameElement.getChildNodes();
225
				String val = textFNList.item(0).getNodeValue();
226
227
				if (val.startsWith(oldPath)) {
228
					val = newPath + val.substring(oldPath.length());
229
					textFNList.item(0).setNodeValue(val);
230
					changed = true;
231
				}
232
			}// end of if clause
233
234
		}// end of for loop with s var
235
		return changed;
236
	}
237
238
	/**
239
	 * Get the project name in the .project xml file.
240
	 * 
241
	 * @return the project name
242
	 */
243
/*	private String getProjectName() {
244
245
		// get the root element
246
		Element docEle = dom.getDocumentElement();
247
248
		Node first = docEle.getFirstChild();
249
		Node last = docEle.getLastChild();
250
		Node curr = first;
251
252
		while (curr != last) {
253
			if (curr.getNodeName().equals("name")) { //$NON-NLS-1$
254
255
				return curr.getTextContent();
256
			}
257
			curr = curr.getNextSibling();
258
		}
259
		return null;
260
	}
261
*/
262
	/**
263
	 * Save the .profile file.
264
	 * 
265
	 * @return true if successful otherwise false
266
	 */
267
	private boolean saveProjectFile(IPath filePath, Document dom) throws Exception {
268
269
270
		// Serialization through Transform.
271
		File filename = filePath.toFile();
272
273
		DOMSource domSource = new DOMSource(dom);
274
		StreamResult streamResult = new StreamResult(filename);
275
		TransformerFactory tf = TransformerFactory.newInstance();
276
277
		Transformer serializer = tf.newTransformer();
278
		serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
279
		serializer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
280
		serializer.transform(domSource, streamResult);
281
282
		return true;
283
	}
284
285
	/*
286
	 * Performs the project renaming operation. The project name in the .project
287
	 * files are renamed and any linked directory resources are
288
	 * remapped.
289
	 * 
290
	 * @return true if successful otherwise false
291
	 */
292
/*	public boolean performProjectRenaming(IProgressMonitor monitor) throws Exception {
293
		monitor.beginTask( "", projectFiles.length ); //$NON-NLS-1$
294
		if (parseProjectFile()) {
295
			String projName;
296
297
			// get the project name in the .project file
298
			projName = getProjectName();
299
			if (projName == null) {
300
				monitor.done();
301
				return false;
302
			}
303
304
			// handle the linked directories in the .project file
305
			if (oldLinkPathPrefix != null && newLinkPathPrefix != null
306
					&& !oldLinkPathPrefix.equals("")) { //$NON-NLS-1$
307
				if ( processLinkedResources(oldLinkPathPrefix, newLinkPathPrefix) == true ) {
308
					saveProjectFile();
309
				}
310
			}
311
312
			// rename the project name in the .project 
313
			String data;
314
			String new_data;
315
316
			// process the .project file
317
			data = readFileIntoString(projectFile);
318
319
			new_data = data
320
					.replaceAll("\\b" + projName + "\\b", newProjectName);  //$NON-NLS-1$//$NON-NLS-2$
321
			if (!data.equals(new_data)) {
322
				writeStringIntoFile(projectFile, new_data);
323
			}
324
			monitor.worked(1);
325
			IExecutableExtension[] extensions = getMigrationHelpers();
326
			if( extensions.length == 0 ) {
327
				monitor.done();
328
				return true;
329
			}			
330
			for( int i = 0; i < projectFiles.length; i++ ) {
331
				if( projectFiles[i].getName().equals(IProjectDescription.DESCRIPTION_FILE_NAME) ) {
332
					continue;
333
				}
334
335
336
				for( int j = 0; j < extensions.length; j ++ ) {
337
					if (extensions[j] instanceof ProjectMigrationHelper) {
338
						ProjectMigrationHelper helper = (ProjectMigrationHelper) extensions[j];
339
						IPath filePath = projectPath.append( projectFiles[i].getName());
340
						helper.migrateFile( filePath, projName, newProjectName, oldLinkPathPrefix, newLinkPathPrefix);
341
					}
342
				}
343
				monitor.worked(1);
344
			}
345
		}
346
347
		monitor.done();
348
		return true;
349
	}
350
	*/
351
	/*
352
	 * Get the set of migration helpers. We don't match on the natures since no
353
	 * projects are actually open. Instead, the migration helper must "know" which
354
	 * files it can help migrate.
355
	 */
356
	/*
357
	private IExecutableExtension[] getMigrationHelpers() {
358
		List helpers = new ArrayList();
359
360
		try {
361
	        IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_MIGRATION_HELPERS);
362
			if (extension != null) {
363
				IExtension[] extensions = extension.getExtensions();
364
				for (int i = 0; i < extensions.length; i++ ) {
365
					IExtension extension2 = extensions[i]; 
366
					IConfigurationElement[] configElements = extension2.getConfigurationElements();
367
					for ( int j = 0; j < configElements.length; j ++ ) {
368
						IConfigurationElement configElement = configElements[j];
369
						if( configElement.getAttribute( "class" ) != null ) { //$NON-NLS-1$
370
							helpers.add( configElement.createExecutableExtension("class")); //$NON-NLS-1$
371
						}
372
					}
373
				}
374
			}
375
		} catch (CoreException e) {
376
			ResourcesPlugin.getPlugin().getLog().log(new Status( IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, Messages.getString("ExportProjectMigrationInfo.4"), e));  //$NON-NLS-1$
377
		}
378
		
379
		return (IExecutableExtension[]) helpers.toArray(new IExecutableExtension[0]);
380
			
381
	}
382
*/	
383
}
384
385
(-)src/org/eclipse/core/internal/resources/projectmigration/SnapInfoStore.java (+260 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006, 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Wind River Systems, Inc. - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.core.internal.resources.projectmigration;
12
13
import java.io.*;
14
import java.util.*;
15
import org.eclipse.core.filesystem.*;
16
import org.eclipse.core.runtime.*;
17
18
/**
19
 * This class writes and reads a file which represent a snapshot of a particular
20
 * directory and all of its contained files
21
 */
22
23
public class SnapInfoStore {
24
	String rootPath; // the root directory for the snapshot
25
	File storeFile; // the file to write to or read from
26
	int fileCount; // total number of files in the store
27
	int rootLocals; // number of spaces reserved for local
28
	List excludeCheckPathList;	// list containing the canonical paths of symlinks and 
29
								// their immediate parents
30
31
	// pass-through files in the root directory
32
33
	public SnapInfoStore(String rootPath, File storeFile, int rootLocals) {
34
		this.rootPath = rootPath;
35
		this.storeFile = storeFile;
36
		this.rootLocals = rootLocals;
37
	}
38
39
	public SnapInfoStore(String rootPath, File storeFile) {
40
		this.rootPath = rootPath;
41
		this.storeFile = storeFile;
42
		this.rootLocals = 0;
43
	}
44
45
	public boolean write(IProgressMonitor monitor) {
46
		boolean ret = false;
47
		if (!rootPath.equals("")) { //$NON-NLS-1$
48
			IFileStore rootStore = EFS.getLocalFileSystem().getStore(
49
					new Path(rootPath));
50
			IFileInfo info = rootStore.fetchInfo();
51
			if (info != null && info.exists()) {
52
				try {
53
					storeFile.delete();
54
					fileCount = 1;
55
					RandomAccessFile out = new RandomAccessFile(storeFile, "rw"); //$NON-NLS-1$
56
					out.writeInt(0); // will be rewritten with total file count
57
					// write dummy record for root directory
58
					out.writeInt(SnapInfo.ATTRIBUTE_DIRECTORY);
59
					out.writeLong(0);
60
					out.writeLong(0);
61
					IPath path = new Path(rootPath);
62
					String name = path.lastSegment();
63
					out.writeUTF(name != null ? name : ""); //$NON-NLS-1$
64
					ret = writeChildren(monitor, out, rootStore);
65
					out.seek(0);
66
					out.writeInt(fileCount);
67
					out.close();
68
				} catch (IOException e) {
69
					return false;
70
				}
71
			}
72
		}
73
		return ret;
74
	}
75
76
	public SnapInfo[] read(IProgressMonitor monitor) {
77
		try {
78
			if (storeFile.exists()) {
79
				RandomAccessFile in = new RandomAccessFile(storeFile, "r"); //$NON-NLS-1$
80
				int totalCount = in.readInt();
81
				if (totalCount != 0) {
82
					SnapInfo[] infos = new SnapInfo[totalCount + rootLocals];
83
					fileCount = 0;
84
					SnapInfo snap = readInfo(in); // read root entry
85
					infos[0] = snap;
86
					fileCount = rootLocals + 1; // reserve for root locals
87
					snap = readChildren(in, 0, infos);
88
					snap.setNextIndex(0); // end of root dir entries
89
					return infos;
90
				}
91
			}
92
		} catch (IOException e) {
93
			return null;
94
		}
95
		return null;
96
	}
97
98
	private boolean writeChildren(IProgressMonitor monitor,
99
			RandomAccessFile out, IFileStore parent) {
100
		try {
101
			Set childrenToExclude = new HashSet();
102
			if(excludeCheckPathList == null)
103
			{
104
				excludeCheckPathList = new ArrayList();
105
				excludeCheckPathList.add(rootPath);
106
			}
107
			
108
			IFileStore[] fileStores = parent.childStores(EFS.NONE, monitor);
109
			String parentCanonicalPath = parent.toLocalFile(EFS.NONE, monitor).getCanonicalPath();
110
			boolean parentAdded = false;
111
			for(int i = 0; i < fileStores.length; i++)
112
			{
113
				File file = fileStores[i].toLocalFile(EFS.NONE, monitor);
114
				// Check if the file is a symlinked directory.
115
				if(parentCanonicalPath != null && file != null)
116
				{
117
					String fileAbsPath = file.getAbsolutePath();
118
					String fileCanonicalPath = file.getCanonicalPath();					
119
					boolean childToExcludeFound = false; 
120
					if(file.isDirectory() && (!fileAbsPath.equals(fileCanonicalPath)))
121
					{
122
						// Check to see if the symlinked child canonical path is a substring of parent path or
123
						// in other words, check if the parent path starts with the child canonical path.
124
						if (parentCanonicalPath.startsWith(fileCanonicalPath))
125
						{
126
							childrenToExclude.add(file.getName());
127
//							System.out.println("Recursion detected, excluding - [" + fileAbsPath + "] , [" + fileCanonicalPath + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
128
//							System.out.println("Symlink refers to an ancestor of this path - " + parentCanonicalPath); //$NON-NLS-1$
129
							continue;
130
						}
131
						
132
						// Check if any of the collected paths starts with this child symlink cannonical path.
133
						// or in other words check if child symlink canonical path is a substring of parent canonical path.
134
						Iterator iter = excludeCheckPathList.iterator();						
135
						while(iter.hasNext())
136
						{
137
							String excludeCheckPathListStr = (String) iter.next();
138
							if(excludeCheckPathListStr.startsWith(fileCanonicalPath))
139
							{
140
								childrenToExclude.add(file.getName());
141
								childToExcludeFound = true;
142
//								System.out.println("Recursion detected, excluding - [" + file.getAbsolutePath() + "] , [" + file.getCanonicalPath() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
143
//								System.out.println("Recursion detected against a previously included parent's path - " + excludeCheckPathListStr); //$NON-NLS-1$
144
								break;
145
							}
146
						}
147
						
148
						if(childToExcludeFound)
149
						{
150
							continue;
151
						}
152
						
153
						if (!parentAdded)
154
						{
155
							excludeCheckPathList.add(parentCanonicalPath);
156
							parentAdded = true;
157
						}
158
						
159
						excludeCheckPathList.add(fileCanonicalPath);						
160
					}
161
				}
162
				else
163
				{
164
//					System.out.println("File is null - " + fileStores[i].getName());  //$NON-NLS-1$
165
				}
166
			}			
167
			
168
			String[] children = parent.childNames(EFS.NONE, monitor);			
169
			List childrenWithoutRecursiveLinksList = new ArrayList();			
170
			// exclude the recursive links from children from the collected set of files.
171
			for(int i = 0; i < children.length; i++)
172
			{
173
				if(!childrenToExclude.contains(children[i]))
174
				{
175
					childrenWithoutRecursiveLinksList.add(children[i]);					
176
				}						
177
			}			
178
			String[] childrenWithoutRecursiveLinks = (String[]) childrenWithoutRecursiveLinksList.toArray(new String[childrenWithoutRecursiveLinksList.size()]);			
179
			out.writeInt(childrenWithoutRecursiveLinks.length);
180
			for (int i = 0; i < childrenWithoutRecursiveLinks.length; i++) {
181
				IFileStore store = parent.getChild(childrenWithoutRecursiveLinks[i]);
182
				// possible speedup if following line calls fetchInfo()?
183
				IFileInfo info = store.fetchInfo(EFS.NONE, monitor);
184
				if (!writeInfo(out, info))
185
					return false;
186
				if (info.isDirectory() && !writeChildren(monitor, out, store))
187
					return false;
188
			}
189
			return true;
190
		} catch (CoreException e) {
191
			return false;
192
		} catch (IOException e) {
193
			return false;
194
		}
195
	}
196
197
	private boolean writeInfo(RandomAccessFile out, IFileInfo info) {
198
		try {
199
			int attributes = 0;
200
			if (info.getAttribute(EFS.ATTRIBUTE_ARCHIVE))
201
				attributes |= EFS.ATTRIBUTE_ARCHIVE;
202
			if (info.getAttribute(EFS.ATTRIBUTE_EXECUTABLE))
203
				attributes |= EFS.ATTRIBUTE_EXECUTABLE;
204
			if (info.getAttribute(EFS.ATTRIBUTE_HIDDEN))
205
				attributes |= EFS.ATTRIBUTE_HIDDEN;
206
			// if (info.getAttribute(EFS.ATTRIBUTE_SYMLINK))
207
			// attributes |= EFS.ATTRIBUTE_SYMLINK;
208
			if (info.getAttribute(EFS.ATTRIBUTE_READ_ONLY))
209
				attributes |= EFS.ATTRIBUTE_READ_ONLY;
210
			if (info.isDirectory())
211
				attributes |= SnapInfo.ATTRIBUTE_DIRECTORY;
212
			out.writeInt(attributes);
213
			// if ((attributes & EFS.ATTRIBUTE_SYMLINK) != 0) {
214
			// String link = info.getStringAttribute(EFS.ATTRIBUTE_LINK_TARGET);
215
			// out.writeUTF(link);
216
			// }
217
			out.writeLong(info.getLastModified());
218
			out.writeLong(info.getLength());
219
			out.writeUTF(info.getName());
220
			++fileCount;
221
			return true;
222
		} catch (IOException e) {
223
			return false;
224
		}
225
	}
226
227
	private SnapInfo readChildren(RandomAccessFile in, int parentIndex,
228
			SnapInfo[] infos) throws IOException {
229
		SnapInfo snap = null;
230
		int nChildren = in.readInt();
231
		for (int i = 0; i < nChildren; i++) {
232
			snap = readInfo(in);
233
			infos[fileCount++] = snap;
234
			if (snap.isDirectory()) {
235
				snap.setChildIndex(fileCount); // assume non-empty
236
				SnapInfo last = readChildren(in, fileCount - 1, infos);
237
				if (last != null)
238
					last.setNextIndex(0); // end of this directory
239
				else
240
					snap.setChildIndex(0); // directory was empty
241
			}
242
			snap.setNextIndex(fileCount);
243
			snap.setParentIndex(parentIndex);
244
		}
245
		return snap;
246
	}
247
248
	private SnapInfo readInfo(RandomAccessFile in) throws IOException {
249
		int attributes = in.readInt();
250
		long lastModified = in.readLong();
251
		long length = in.readLong();
252
		String name = in.readUTF();
253
		SnapInfo snap = new SnapInfo(name);
254
		snap.setAttributes(attributes);
255
		snap.setLastModified(lastModified);
256
		snap.setLength(length);
257
		return snap;
258
	}
259
260
}
(-)src/org/eclipse/core/resources/projectmigration/ExportProjectMigrationInfo.java (+305 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     Wind River Systems, Inc. - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.core.resources.projectmigration;
12
13
import org.eclipse.core.internal.resources.projectmigration.Messages;
14
15
import java.io.File;
16
import java.io.FileInputStream;
17
import java.io.FileOutputStream;
18
import java.io.InputStream;
19
import java.io.IOException;
20
import java.io.OutputStream;
21
import java.util.ArrayList;
22
import java.util.List;
23
import java.util.zip.Deflater;
24
import java.util.zip.ZipEntry;
25
import java.util.zip.ZipOutputStream;
26
//import org.eclipse.core.resources.IFile;
27
import org.eclipse.core.resources.IProject;
28
import org.eclipse.core.resources.IProjectDescription;
29
import org.eclipse.core.resources.IWorkspaceRunnable;
30
import org.eclipse.core.resources.ResourcesPlugin;
31
import org.eclipse.core.runtime.CoreException;
32
import org.eclipse.core.runtime.IConfigurationElement;
33
import org.eclipse.core.runtime.IExecutableExtension;
34
import org.eclipse.core.runtime.IExtension;
35
import org.eclipse.core.runtime.IExtensionPoint;
36
import org.eclipse.core.runtime.IProgressMonitor;
37
import org.eclipse.core.runtime.IStatus;
38
//import org.eclipse.core.runtime.NullProgressMonitor;
39
import org.eclipse.core.runtime.OperationCanceledException;
40
//import org.eclipse.core.runtime.Path;
41
import org.eclipse.core.runtime.Platform;
42
import org.eclipse.core.runtime.Status;
43
import org.eclipse.core.runtime.SubProgressMonitor;
44
import org.eclipse.core.internal.resources.projectmigration.SFSUtilities;
45
/**
46
 * 
47
 */
48
public class ExportProjectMigrationInfo implements IWorkspaceRunnable {
49
	private IProject fProject;		// project that is being exported
50
 
51
52
53
	/**
54
	 * 
55
	 */
56
	public ExportProjectMigrationInfo(IProject project) {
57
		fProject = project;
58
	}
59
60
 	private boolean findMatch( String id, String[] list ) {
61
		for( int i = 0; i < list.length; i++ ) {
62
			if( list[i].equalsIgnoreCase( id ) ) {
63
				return true;
64
			}
65
		}
66
		return false;
67
	}
68
 	/*
69
 	 * Get the list of migration helpers that match on at least one of the natures in the project.
70
 	 * If the nature in the extension is "*", then it matches any project.
71
 	 * If the nature in the extension is "+", then it matches only if some other extension matches
72
 	 */
73
	private IExecutableExtension[] getMigrationHelpers() {
74
		
75
		List helpers = new ArrayList();
76
		List possibleHelpers = new ArrayList();
77
		/*
78
		 * Get the list of natures for the project and find matching extensions.
79
		 */
80
		try {
81
			String[] natureIds = fProject.getDescription().getNatureIds();
82
	        IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_MIGRATION_HELPERS);
83
			if (extension != null) {
84
				IExtension[] extensions = extension.getExtensions();
85
				for (int i = 0; i < extensions.length; i++ ) {
86
					IExtension extension2 = extensions[i]; 
87
					boolean matchNature = false;
88
					boolean possibleMatch = false;
89
					IConfigurationElement classConfigElement = null;
90
					IConfigurationElement[] configElements = extension2.getConfigurationElements();
91
					for ( int j = 0; j < configElements.length; j ++ ) {
92
						IConfigurationElement configElement = configElements[j];
93
					
94
						String natureID = configElement.getAttribute("nature"); //$NON-NLS-1$
95
						if( natureID != null ) {
96
							if( natureID.equals("+") ) { //$NON-NLS-1$
97
								possibleMatch = true;	// only add to list if something else matches by nature.
98
							} else if( natureID.equals("*") || findMatch( natureID, natureIds ) == true) { //$NON-NLS-1$
99
								matchNature = true;
100
							}
101
						}
102
						String classID = configElement.getAttribute("class"); //$NON-NLS-1$
103
						if( classID != null ) {
104
							classConfigElement = configElement;
105
						}
106
					}
107
					
108
					if( matchNature == true && classConfigElement != null ) {
109
						helpers.add( classConfigElement.createExecutableExtension("class")); //$NON-NLS-1$
110
					} else {
111
						if( possibleMatch == true && classConfigElement != null ) {
112
							possibleHelpers.add( classConfigElement.createExecutableExtension("class")); //$NON-NLS-1$
113
						}
114
					}
115
				}
116
				if( possibleHelpers.size() != 0 && helpers.size() != 0 ) {
117
					possibleHelpers.addAll(helpers);
118
					helpers.clear();
119
					helpers.addAll(possibleHelpers);
120
					possibleHelpers.clear();
121
				}
122
			}
123
		} catch (CoreException e) {
124
			ResourcesPlugin.getPlugin().getLog().log(new Status( IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, Messages.getString("ExportProjectMigrationInfo.4"), e));  //$NON-NLS-1$
125
		}
126
		return (IExecutableExtension[])helpers.toArray( new IExecutableExtension[0]);
127
		
128
		
129
			
130
	}
131
	
132
	/*
133
	 * This function needs to do the following:
134
	 * 1. Find a MigrationHelper for the given project (must match one of the natures)
135
	 * 2. Ask the MigrationHelper to create the zip files for export
136
	 * 3. Create the Resource Refresh information.
137
	 * 4. Create the zip file containing the resource refresh info and any zip files created by the helper.
138
	 * 5. Add placeholders to the zip file to record the names of project files that should be copied
139
	 * later when the project migration is done. Empty files will be written to the zip to record the names.
140
	 * 
141
	 * If there is not a migrationHelper, then this operation will not do anything. It should fail.
142
	 */
143
	public void run(IProgressMonitor monitor) throws CoreException {
144
		monitor.beginTask("", 100 ); //$NON-NLS-1$
145
		monitor.setTaskName(Messages.getString("ExportProjectMigrationInfo.5"));  //$NON-NLS-1$
146
		/*
147
		 * Find a MigrationHelper for the given project (must match one of the natures)
148
		 */
149
		IExecutableExtension[] extensions = getMigrationHelpers();
150
		if( extensions == null || extensions.length == 0 ) {
151
			monitor.done();
152
			return;
153
		}
154
			
155
		/*
156
		 * Ask the helpers to create the zip files for export
157
		 */
158
		List zipFilesForExport = new ArrayList();
159
		List filesToMigrate = new ArrayList();
160
//		filesToMigrate.add( IProjectDescription.DESCRIPTION_FILE_NAME );
161
		for( int i = 0; i < extensions.length; i ++ ) {
162
			if (extensions[i] instanceof ProjectMigrationHelper) {
163
				ProjectMigrationHelper helper = (ProjectMigrationHelper) extensions[i];
164
				helper.setProject( fProject );
165
				helper.createExportFiles(new SubProgressMonitor(monitor, 40/extensions.length));
166
				zipFilesForExport.addAll( helper.getExportZipFiles());
167
				filesToMigrate.addAll(helper.getFilesToMigrate());
168
			}
169
		}
170
		
171
		/*
172
		 * Create the resource refresh information
173
		 */
174
		monitor.setTaskName(Messages.getString("ExportProjectMigrationInfo.6")); //$NON-NLS-1$
175
		IProjectDescription desc = fProject.getDescription();
176
		File tmpfile;
177
		try {
178
				tmpfile = File.createTempFile("tmp", ".snap");  //$NON-NLS-1$//$NON-NLS-2$
179
				SFSUtilities.exportRefreshInfo(desc, tmpfile, new SubProgressMonitor(monitor, 10));
180
		} catch (IOException e) {
181
			throw new CoreException(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.0"), e)); //$NON-NLS-1$
182
		}
183
		
184
		
185
		/*
186
		 * Create the zip file containing the resource refresh info and any zip files created by the helper.
187
		 * Files to add to the zip file include
188
		 *     tmpfile  - entry is .projdir.snap
189
		 *     all files in zipFilesForExport
190
		 *     placeholders for everything in filesToMigrate
191
		 */
192
		int ticks = 50/(1 + zipFilesForExport.size() + filesToMigrate.size());
193
		File targetLocationFile = fProject.getLocation().append(ProjectMigration.MIGRATION_ZIP_NAME).toFile();
194
		targetLocationFile.delete();
195
		ZipOutputStream out= null;
196
		try {
197
			targetLocationFile.getParentFile().mkdirs();
198
			out= new ZipOutputStream(new FileOutputStream(targetLocationFile));
199
			out.setLevel(Deflater.BEST_COMPRESSION);
200
			checkMonitor(monitor);
201
 			writeEntry(out, ProjectMigration.SNAP_NAME, tmpfile, new SubProgressMonitor( monitor, ticks ));
202
 			for( int i = 0; i < zipFilesForExport.size(); i++) {
203
 				ProjectMigrationHelper.ExportZipFileEntryInfo info = (ProjectMigrationHelper.ExportZipFileEntryInfo) zipFilesForExport.get(i);
204
 				writeEntry(out, info.getName(), info.getFile(), new SubProgressMonitor( monitor, ticks ) );
205
 			}
206
 			for( int i = 0; i < filesToMigrate.size(); i++ ) {
207
 				String name = (String) filesToMigrate.get(i);
208
 				writePlaceHolder( out, name, new SubProgressMonitor( monitor, ticks ) );
209
 			}
210
 			for( int i = 0; i < extensions.length; i ++ ) {
211
 				if (extensions[i] instanceof ProjectMigrationHelper) {
212
 					ProjectMigrationHelper helper = (ProjectMigrationHelper) extensions[i];
213
 					helper.setProject( fProject );
214
 					helper.removeExportFiles();
215
 				}
216
 			}
217
 
218
		}
219
		catch (IOException e) {
220
			throw new CoreException( new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.3"), e)); //$NON-NLS-1$
221
222
		}
223
		finally {
224
			close(out);
225
		}
226
		
227
		/*
228
		 * TODO: what is the following code trying to do? (make the .settings part of the project?)
229
		 */
230
/*		IFile[] wsResource= ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(new Path(targetLocationFile.getAbsolutePath()));
231
		for (int i = 0; i < wsResource.length; i++) {
232
			IFile file = wsResource[i];
233
			file.refreshLocal(0, new NullProgressMonitor());
234
		}
235
*/
236
		monitor.done();
237
238
	}
239
	private void checkMonitor(IProgressMonitor monitor) {
240
		if (monitor.isCanceled()) {
241
			throw new OperationCanceledException();
242
		}
243
	}
244
	private void writeEntry(ZipOutputStream out, String name, File input, IProgressMonitor monitor) throws IOException {
245
		monitor.beginTask("", 100); //$NON-NLS-1$
246
		monitor.subTask(name);
247
		ZipEntry e= new ZipEntry(name);
248
		out.putNextEntry(e);
249
		int read= 0;
250
		byte[] buffer= new byte[4096];
251
		InputStream in= new FileInputStream(input);
252
		long totalBytes = input.length();
253
		long totalDone = 0;
254
		try {
255
			while ((read= in.read(buffer)) >= 0) {
256
				out.write(buffer, 0, read);
257
				totalDone += read;
258
				long ticks = (totalDone * 100)/totalBytes;
259
				if( ticks > 0 ) {
260
					monitor.worked( (int)ticks);
261
					totalDone -= (ticks * totalBytes)/100;
262
				}
263
				
264
			}
265
			out.closeEntry();
266
		}
267
		finally {
268
			close(in);
269
			monitor.done();
270
		}
271
	}
272
	private void writePlaceHolder(ZipOutputStream out, String name, IProgressMonitor monitor) throws IOException {
273
		monitor.beginTask("", 100); //$NON-NLS-1$
274
		monitor.subTask(name);
275
		ZipEntry e= new ZipEntry(name);
276
		out.putNextEntry(e);
277
		try {
278
			out.closeEntry();
279
		}
280
		finally {
281
			monitor.done();
282
		}
283
	}
284
	private void close(InputStream in) {
285
		try {
286
			if (in != null) { 
287
				in.close();
288
			}
289
		} catch (IOException e) {
290
			ResourcesPlugin.getPlugin().getLog().log( new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.1"), e)); //$NON-NLS-1$
291
		}
292
	} 
293
294
	private void close(OutputStream out) {
295
		try {
296
			if (out != null) {
297
				out.close();
298
			}
299
		} catch (IOException e) {
300
			ResourcesPlugin.getPlugin().getLog().log( new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.2"), e)); //$NON-NLS-1$
301
302
		}
303
	} 
304
305
}
(-)src/org/eclipse/core/internal/resources/projectmigration/SFSFileSystem.java (+373 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) 2008 Wind River Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors: 
9
 *     Wind River Systems - Initial API and implementation
10
 **********************************************************************/
11
12
package org.eclipse.core.internal.resources.projectmigration;
13
14
import org.eclipse.core.resources.ResourcesPlugin;
15
16
17
import java.io.File;
18
import java.net.URI;
19
import java.net.URISyntaxException;
20
21
22
import org.eclipse.core.filesystem.EFS;
23
import org.eclipse.core.filesystem.IFileInfo;
24
import org.eclipse.core.filesystem.IFileStore;
25
import org.eclipse.core.filesystem.provider.FileSystem;
26
import org.eclipse.core.filesystem.URIUtil;
27
import org.eclipse.core.runtime.IStatus;
28
import org.eclipse.core.runtime.IPath;
29
import org.eclipse.core.runtime.IProgressMonitor;
30
import org.eclipse.core.runtime.Path;
31
import org.eclipse.core.runtime.Status;
32
33
/**
34
 * This is the snapshot file system. It reads a snapshot of a file tree, and
35
 * then uses the snapshot information to supply file information to the users of
36
 * the file system.
37
 * 
38
 * The URI's for this system are as follows:
39
 * 
40
 * snapfs:///<path_in_projdir>?<proj_dir>#<snap_file>
41
 * 
42
 * For example:
43
 * 
44
 * snapfs:///.project?/vob/proj#projdir.snap
45
 * 
46
 * The only complicated part is that we allow the user to specify a certain
47
 * number of files, found in the root directory of the snapshot, to be
48
 * "passed through" to the local file system rather than being processed via the
49
 * snapshot information. The number of such files which may be defined is
50
 * specified by the static variable rootLocals, and their names are added to a
51
 * static list.
52
 * 
53
 */
54
55
public class SFSFileSystem extends FileSystem {
56
	public SFSFileSystem() {
57
		super();
58
		sfsFileSystem = this;
59
	}
60
61
	private static SFSFileSystem sfsFileSystem;
62
63
	public static final String SCHEME = "snapfs"; //$NON-NLS-1$
64
65
	static private String rootFilePath = null;
66
	static private String[] rootLocalNames;
67
	private SnapInfo[] snapInfos;
68
	static private int rootLocals;
69
70
	// same as FileInfo.ATTRIBUTE_DRECTORY which is unfortunately private
71
	static int ATTRIBUTE_DIRECTORY = 1 << 0;
72
73
	// Only one snapfs file system can be used at any time,
74
	// although there is currently no protection against this.
75
	// Since the feature is designed to work only during what
76
	// we call "project migration", we assume that such migrations
77
	// will only occur sequentially. The static nature of the
78
	// file system is required because the constructor is called
79
	// from within the EFS (Eclipse File System).
80
81
	public static SFSFileSystem getSFSFileSystem() {
82
		return sfsFileSystem;
83
	}
84
85
	// Set the root path for the directory tree whose contents is
86
	// described in the snap info file. Also, specify the number
87
	// of "root local" files which will be passed through to the
88
	// local file system. Calling this method activates the use
89
	// of the snapshot file refresh information.
90
	static public void setRootPath(String rootPath, int numberofRootLocals) {
91
		rootFilePath = rootPath;
92
		rootLocals = numberofRootLocals;
93
		rootLocalNames = new String[numberofRootLocals];
94
	}
95
96
	// Load the snapshot from the refresh info file created during
97
	// the migration export operation. This method is called from
98
	// getURI if a non-null root file path is present but the
99
	// "snapInfos" array is null.
100
	private boolean loadSnapshot(IProgressMonitor monitor, String path,
101
			String snapFilePath) {
102
		IPath fullPath = new Path(rootFilePath);
103
		String rootName = fullPath.lastSegment();
104
		fullPath = fullPath.append(snapFilePath);
105
		File snapFile = new File(fullPath.toString());
106
		SnapInfoStore store = new SnapInfoStore(path, snapFile, rootLocals);
107
		snapInfos = store.read(monitor);
108
		if (snapInfos == null) {
109
			stopUsingRefreshInfo(); // turn off redirection
110
			return false;
111
		}
112
		snapInfos[0].setName(rootName); // set name of root directory
113
		snapInfos[0].setChildIndex(rootLocals + 1);
114
		// Now check each "pass through" file to see if it is present in
115
		// the snapshot info; if so, adjust the links so it is skipped.
116
		for (int i = 0; i < rootLocals; i++) {
117
			String name = rootLocalNames[i];
118
			if (name == null)
119
				break; // end of root locals (not all need be used)
120
			int prev = 0; // will update snapInfos[0] if first entry matches
121
			for (int x = rootLocals + 1; x != 0 && x < snapInfos.length;) {
122
				if (snapInfos[x].getName().equals(name)) {
123
					snapInfos[prev].setNextIndex(snapInfos[x].getNextIndex());
124
					break;
125
				}
126
				prev = x;
127
				x = snapInfos[x].getNextIndex();
128
			}
129
			// Get the file info from the local file system and place it
130
			// in the snapInfos array.
131
			fullPath = fullPath.removeLastSegments(1).append(name);
132
			IFileStore localStore = EFS.getLocalFileSystem().getStore(fullPath);
133
			IFileInfo info = localStore.fetchInfo();
134
			SnapInfo snap = new SnapInfo(name);
135
			int attributes = 0;
136
			if (info.getAttribute(EFS.ATTRIBUTE_ARCHIVE))
137
				attributes |= EFS.ATTRIBUTE_ARCHIVE;
138
			if (info.getAttribute(EFS.ATTRIBUTE_EXECUTABLE))
139
				attributes |= EFS.ATTRIBUTE_EXECUTABLE;
140
			if (info.getAttribute(EFS.ATTRIBUTE_HIDDEN))
141
				attributes |= EFS.ATTRIBUTE_HIDDEN;
142
			if (info.getAttribute(EFS.ATTRIBUTE_SYMLINK))
143
				attributes |= EFS.ATTRIBUTE_SYMLINK;
144
			if (info.getAttribute(EFS.ATTRIBUTE_READ_ONLY))
145
				attributes |= EFS.ATTRIBUTE_READ_ONLY;
146
			if (info.isDirectory())
147
				attributes |= ATTRIBUTE_DIRECTORY;
148
			snap.setAttributes(attributes);
149
			snap.setLastModified(info.getLastModified());
150
			snap.setLength(info.getLength());
151
			snapInfos[i + 1] = snap;
152
		}
153
		return true;
154
	}
155
156
	// Discontinue use of the snapshot file refresh information.
157
	// All further references to elements of this file system are
158
	// forwarded to the local file system.
159
	static public void stopUsingRefreshInfo() {
160
		rootFilePath = null;
161
		rootLocals = 0;
162
		rootLocalNames = null;
163
		if (sfsFileSystem != null)
164
			sfsFileSystem.snapInfos = null;
165
	}
166
167
	// Add the name of a "root local file" to the list. Return true
168
	// if successful, or false if no additional root local files can
169
	// be added. Note that a root local file should not be a directory,
170
	// as the algorithm in the childCount method will not work correctly
171
	// in that case.
172
	static public boolean setRootLocalFile(String name) {
173
		for (int i = 0; i < rootLocals; i++)
174
			if (rootLocalNames[i] == null) {
175
				rootLocalNames[i] = name;
176
				return true;
177
			}
178
		return false;
179
	}
180
181
	// Check if the index into the snapshot file information is for
182
	// a root local file. (Only to be called from SFSFileStore)
183
	static public boolean isRootLocalFileStore(int snapIndex) {
184
		return snapIndex >= 0 && snapIndex < rootLocals
185
				&& rootLocalNames[snapIndex] != null;
186
	}
187
188
	// Check if the name is that of a file in the root local file list.
189
	public boolean isRootLocalFile(String name) {
190
		for (int i = 0; i < rootLocals && rootLocalNames[i] != null; i++)
191
			if (rootLocalNames[i].equals(name))
192
				return true;
193
		return false;
194
	}
195
196
	// Return a count of the children of the file identified by "snapIndex".
197
	// (Only to be called from SFSFileStore)
198
	private int childCount(int snapIndex) {
199
		if (snapInfos == null || snapIndex < 0 || snapIndex >= snapInfos.length
200
				|| !snapInfos[snapIndex].isDirectory()) {
201
			return 0;
202
		}
203
		int count = 0;
204
		int x = snapInfos[snapIndex].getChildIndex();
205
		if (snapIndex == 0) {
206
			for (int i = 1; i <= rootLocals && snapInfos[i] != null; i++)
207
				++count; // count the root locals
208
		}
209
		for (; x != 0 && x < snapInfos.length;) {
210
			++count;
211
			x = snapInfos[x].getNextIndex();
212
		}
213
		return count;
214
	}
215
216
	// Return the child IFileInfo array for the directory specified
217
	// by "snapIndex". (Only to be called from SFSFileStore)
218
	public IFileInfo[] childInfos(int snapIndex) {
219
		int n = childCount(snapIndex);
220
		if (n == 0)
221
			return new IFileInfo[0];
222
		IFileInfo[] children = new SnapInfo[n];
223
		int x = snapInfos[snapIndex].getChildIndex();
224
		int i = 0;
225
		if (snapIndex == 0) {
226
			for (int j = 1; j <= rootLocals && snapInfos[j] != null; j++)
227
				children[i++] = snapInfos[j];
228
		}
229
		for (; i < n; i++) {
230
			children[i] = snapInfos[x];
231
			x = snapInfos[x].getNextIndex();
232
		}
233
		return children;
234
	}
235
236
	// Return the child IFileStore array for the directory specified
237
	// by "snapIndex". (Only to be called from SFSFileStore)
238
	public IFileStore[] childStores(int snapIndex) {
239
		int n = childCount(snapIndex);
240
		if (n == 0)
241
			return new IFileStore[0];
242
		IFileStore[] children = new SFSFileStore[n];
243
		int x = snapInfos[snapIndex].getChildIndex();
244
		int i = 0;
245
		if (snapIndex == 0) {
246
			for (int j = 1; j <= rootLocals && snapInfos[j] != null; j++) {
247
				IPath path = new Path(rootFilePath).append(rootLocalNames[i]);
248
				children[i++] = getStore(path);
249
			}
250
		}
251
		for (; i < n; i++) {
252
			children[i] = new SFSFileStore(x);
253
			x = snapInfos[x].getNextIndex();
254
		}
255
		return children;
256
	}
257
258
	// Return the SnapInfo (an implementor of IFileInfo) for the file
259
	// specified by "snapIndex". (Only to be called from SFSFileStore)
260
	public SnapInfo fetchInfo(int snapIndex) {
261
		if (snapInfos == null || snapIndex < 0 || snapIndex >= snapInfos.length) {
262
			return null;
263
		}
264
		return snapInfos[snapIndex];
265
	}
266
267
	// Return the IFileStore for the named child of the directory
268
	// specified by "snapIndex". (Only to be called from SFSFileStore)
269
	public IFileStore getChild(int snapIndex, String name) {
270
		if (snapInfos == null || snapIndex < 0 || snapIndex >= snapInfos.length
271
				|| !snapInfos[snapIndex].isDirectory()) {
272
			return null; // ??? should return something
273
		}
274
		if (snapIndex == 0 && isRootLocalFile(name)) {
275
			IPath path = new Path(rootFilePath);
276
			path = path.append(name);
277
			return EFS.getLocalFileSystem().getStore(path);
278
		}
279
		int x = snapInfos[snapIndex].getChildIndex();
280
		while (x != 0 && x < snapInfos.length) {
281
			if (snapInfos[x].getName().equals(name))
282
				return new SFSFileStore(x);
283
			x = snapInfos[x].getNextIndex();
284
		}
285
		IPath path = new Path(rootFilePath);
286
		path.append(name);
287
		return EFS.getNullFileSystem().getStore(path);
288
	}
289
290
	// Return the SFSFileStore (an implementor of IFileStore) for
291
	// the root directory of the file refresh information.
292
	// (Only to be called from SFSFileStore)
293
	public SFSFileStore getRoot() {
294
		if (snapInfos == null)
295
			return null;
296
		return new SFSFileStore(0);
297
	}
298
299
	// Return an IFileStore for the specified URI (one which includes
300
	// the "snapfs:" scheme). If use of the refresh info file is not
301
	// currently on, or if there is failure loading the refresh info,
302
	// or if the root file path in the URI (the query portion) is not
303
	// the same as the root file name for the refresh information, or
304
	// if the file specifies a "root local" file, go to the local file
305
	// system for an IFileStore; otherwise, get the SFSFileStore for
306
	// the corresponding file within the refresh information.
307
	public IFileStore getStore(URI uri) {
308
		try {
309
			IPath path = new Path(uri.getPath());
310
			if (rootFilePath == null
311
					|| // use of snapshot is turned off
312
					(snapInfos == null && // or, failure loading snapshot info
313
					!loadSnapshot(null, path.toString(), uri.getFragment()))
314
					|| !uri.getQuery().equals(rootFilePath) || // or, not for
315
					// this root
316
					(path.segmentCount() == 1 && // or, a local file
317
					isRootLocalFile(path.lastSegment()))) {
318
				// refer this to local file system
319
				IPath localPath = new Path(uri.getQuery());
320
				localPath.append(path);
321
				URI localURI = new URI(EFS.SCHEME_FILE, uri.getAuthority(),
322
						localPath.toString(), null, null);
323
				return EFS.getLocalFileSystem().getStore(localURI);
324
			}
325
			SFSFileStore root = getRoot();
326
			if (path.segmentCount() == 0)
327
				return root;
328
			return root.getChild(path);
329
		} catch (URISyntaxException e) {
330
			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES,
331
					"uri", e)); //$NON-NLS-1$
332
			// } catch (CoreException e) {
333
			// Activator.log(e);
334
		}
335
336
		return EFS.getNullFileSystem().getStore(uri);
337
	}
338
339
	public int attributes() {
340
		// return all local file system attributes, even though
341
		// not all files can be written (only pass-through files)
342
		return EFS.getLocalFileSystem().attributes();
343
	}
344
345
	public boolean canDelete() {
346
		return true;
347
	}
348
349
	public boolean canWrite() {
350
		return true;
351
	}
352
353
	public IFileStore fromLocalFile(File file) {
354
		return EFS.getLocalFileSystem().fromLocalFile(file);
355
	}
356
357
	public IFileStore getStore(IPath path) {
358
		return EFS.getLocalFileSystem().getStore(path);
359
	}
360
361
	public boolean isCaseSensitive() {
362
		return EFS.getLocalFileSystem().isCaseSensitive();
363
	}
364
365
	public String rootPath() {
366
		return rootFilePath;
367
	}
368
369
	public URI rootURI() {
370
		return URIUtil.toURI(new Path(rootFilePath));
371
	}
372
373
}
(-)src/org/eclipse/core/internal/resources/projectmigration/SFSFileStore.java (+203 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) 2008 Wind River Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors: 
9
 *     Wind River Systems - Initial API and implementation
10
 **********************************************************************/
11
12
package org.eclipse.core.internal.resources.projectmigration;
13
14
import java.io.File;
15
import java.io.InputStream;
16
import java.io.OutputStream;
17
import java.net.URI;
18
import java.net.URISyntaxException;
19
20
import org.eclipse.core.filesystem.EFS;
21
import org.eclipse.core.filesystem.IFileInfo;
22
import org.eclipse.core.filesystem.IFileStore;
23
import org.eclipse.core.filesystem.IFileSystem;
24
import org.eclipse.core.filesystem.provider.FileStore;
25
import org.eclipse.core.runtime.CoreException;
26
import org.eclipse.core.runtime.IPath;
27
import org.eclipse.core.runtime.IProgressMonitor;
28
import org.eclipse.core.runtime.Path;
29
30
public class SFSFileStore extends FileStore {
31
	private int snapIndex;
32
	private static final String[] nullStringArray = new String[0];
33
34
	public SFSFileStore(int snapIndex) {
35
		this.snapIndex = snapIndex;
36
	}
37
38
	
39
	/**
40
	 * @throws CoreException  
41
	 * @Override
42
	 */
43
	public IFileInfo[] childInfos(int options, IProgressMonitor monitor)
44
			throws CoreException {
45
		return SFSFileSystem.getSFSFileSystem().childInfos(snapIndex);
46
	}
47
48
	/**
49
	 * @throws CoreException 
50
	 * @Override 
51
	 */
52
	public String[] childNames(int options, IProgressMonitor monitor)
53
			throws CoreException {
54
		IFileInfo[] infos = SFSFileSystem.getSFSFileSystem().childInfos(snapIndex);
55
		if (infos == null || infos.length == 0)
56
			return nullStringArray;
57
		String[] children = new String[infos.length];
58
		for (int i = 0; i < infos.length; i++) {
59
			children[i] = infos[i].getName();
60
		}
61
		return children;
62
	}
63
64
	/**
65
	 * @throws CoreException  
66
	 * @Override
67
	 */
68
	public IFileStore[] childStores(int options, IProgressMonitor monitor)
69
			throws CoreException {
70
		return SFSFileSystem.getSFSFileSystem().childStores(snapIndex);
71
	}
72
73
	//@Override
74
	public void copy(IFileStore destination, int options,
75
			IProgressMonitor monitor) throws CoreException {
76
		super.copy(destination, options, monitor);
77
	}
78
79
	//@Override
80
	protected void copyDirectory(IFileInfo sourceInfo, IFileStore destination,
81
			int options, IProgressMonitor monitor) throws CoreException {
82
		super.copyDirectory(sourceInfo, destination, options, monitor);
83
	}
84
85
	//@Override
86
	protected void copyFile(IFileInfo sourceInfo, IFileStore destination,
87
			int options, IProgressMonitor monitor) throws CoreException {
88
		super.copyFile(sourceInfo, destination, options, monitor);
89
	}
90
91
	//@Override
92
	public void delete(int options, IProgressMonitor monitor)
93
			throws CoreException {
94
		super.delete(options, monitor);
95
	}
96
97
	//@Override
98
	public IFileInfo fetchInfo() {
99
		return SFSFileSystem.getSFSFileSystem().fetchInfo(snapIndex);
100
	}
101
102
	/**
103
	 * @throws CoreException 
104
	 * @Override 
105
	 */
106
	public IFileInfo fetchInfo(int options, IProgressMonitor monitor)
107
			throws CoreException {
108
		return fetchInfo();
109
	}
110
111
	//@Override
112
	public IFileStore getChild(String name) {
113
		return SFSFileSystem.getSFSFileSystem().getChild(snapIndex, name);
114
	}
115
116
	//@Override
117
	public IFileSystem getFileSystem() {
118
		return SFSFileSystem.getSFSFileSystem();
119
	}
120
121
	//@Override
122
	public String getName() {
123
		IFileInfo info = SFSFileSystem.getSFSFileSystem().fetchInfo(snapIndex);
124
		if (info != null)
125
			return info.getName();
126
		return null;
127
	}
128
129
	//@Override
130
	public /*SFS*/IFileStore getParent() {
131
		SnapInfo snapInfo = SFSFileSystem.getSFSFileSystem().fetchInfo(
132
				snapIndex);
133
		return new SFSFileStore(snapInfo.getParentIndex());
134
	}
135
136
	//@Override
137
	public IFileStore mkdir(int options, IProgressMonitor monitor)
138
			throws CoreException {
139
		return super.mkdir(options, monitor);
140
	}
141
142
	//@Override
143
	public void move(IFileStore destination, int options,
144
			IProgressMonitor monitor) throws CoreException {
145
		super.move(destination, options, monitor);
146
	}
147
148
	//@Override
149
	public InputStream openInputStream(int options, IProgressMonitor monitor)
150
			throws CoreException {
151
		IPath path = getPath();
152
		return SFSFileSystem.getSFSFileSystem().getStore(path).openInputStream(
153
				options, monitor);
154
	}
155
156
	//@Override
157
	public OutputStream openOutputStream(int options, IProgressMonitor monitor)
158
			throws CoreException {
159
		return super.openOutputStream(options, monitor);
160
	}
161
162
	//@Override
163
	public URI toURI() {
164
165
		URI rootURI = SFSFileSystem.getSFSFileSystem().rootURI();
166
167
		// Build path
168
		IPath path = getPath();
169
		String pathstr = path == null ? null : getPath().toString();
170
171
		try {
172
			URI uri = new URI(SFSFileSystem.SCHEME, rootURI.getAuthority(),
173
					rootURI.getPath(), pathstr, rootURI.getScheme());
174
			return uri;
175
		} catch (URISyntaxException e) {
176
			return null;
177
		}
178
	}
179
180
	public IPath getPath() {
181
		SnapInfo snapInfo = SFSFileSystem.getSFSFileSystem().fetchInfo(snapIndex);
182
		if (snapInfo.getParentIndex() == 0) {
183
			// Parent is root, start at this node
184
			IPath path = new Path(SFSFileSystem.getSFSFileSystem().rootPath());
185
			if (this.snapIndex != 0)
186
				path = path.append(getName());
187
			return path;
188
		}
189
		// Normal path creation
190
		return ((SFSFileStore)getParent()).getPath().append(getName());
191
	}
192
193
	//@Override
194
	public File toLocalFile(int options, IProgressMonitor monitor)
195
			throws CoreException {
196
		if ((options & EFS.CACHE) != 0)
197
			return super.toLocalFile(options, monitor);
198
		if (!SFSFileSystem.isRootLocalFileStore(snapIndex))
199
			return null;
200
		return new File(getPath().toString());
201
	}
202
203
}
(-)plugin.properties (+3 lines)
Lines 28-36 Link Here
28
ExportWizards.FileSystem = File System
28
ExportWizards.FileSystem = File System
29
ExportWizards.Preferences = Preferences
29
ExportWizards.Preferences = Preferences
30
ExportWizards.ZipFile = Archive File
30
ExportWizards.ZipFile = Archive File
31
ExportWizards.ProjectMigrationExport = Project Migration Preparation
31
ExportWizards.FileSystemDescription = Export resources to the local file system.
32
ExportWizards.FileSystemDescription = Export resources to the local file system.
32
ExportWizards.PreferencesDescription = Export preferences to the local file system.
33
ExportWizards.PreferencesDescription = Export preferences to the local file system.
33
ExportWizards.ZipFileDescription = Export resources to an archive file on the local file system.
34
ExportWizards.ZipFileDescription = Export resources to an archive file on the local file system.
35
ExportWizards.ProjectMigrationDescription = Export a snapshot of project information needed for a project migration. 
34
ImportWizards.FileSystem = File System
36
ImportWizards.FileSystem = File System
35
ImportWizards.Preferences = Preferences
37
ImportWizards.Preferences = Preferences
36
ImportWizards.ZipFile = Archive File
38
ImportWizards.ZipFile = Archive File
Lines 39-44 Link Here
39
ImportWizards.PreferencesDescription = Import preferences from the local file system.
41
ImportWizards.PreferencesDescription = Import preferences from the local file system.
40
ImportWizards.ZipFileDescription = Import resources from an archive file into an existing project.
42
ImportWizards.ZipFileDescription = Import resources from an archive file into an existing project.
41
ImportWizards.ExternalProjectDescription = Create new projects from an archive file or directory. 
43
ImportWizards.ExternalProjectDescription = Create new projects from an archive file or directory. 
44
ImportWizards.ProjectMigration = Migrate existing project to a new project directory 
42
NewWizards.Category.Examples = Examples
45
NewWizards.Category.Examples = Examples
43
NewWizards.Category.Basic = General
46
NewWizards.Category.Basic = General
44
NewWizards.project = Project
47
NewWizards.project = Project
(-)plugin.xml (+20 lines)
Lines 66-71 Link Here
66
               class="org.eclipse.core.resources.IResource">
66
               class="org.eclipse.core.resources.IResource">
67
         </selection>
67
         </selection>
68
      </wizard>
68
      </wizard>
69
      <wizard
70
            category="org.eclipse.ui.Basic"
71
            class="org.eclipse.ui.internal.wizards.projectmigration.ProjectMigrationWizard"
72
            icon="$nl$/icons/full/etool16/newprj_wiz.gif"
73
            id="org.eclipse.ui.wizards.import.ProjectMigration"
74
            name="%ImportWizards.ProjectMigration">
75
      </wizard>
69
   </extension>
76
   </extension>
70
   <extension
77
   <extension
71
         point="org.eclipse.ui.exportWizards">
78
         point="org.eclipse.ui.exportWizards">
Lines 111-116 Link Here
111
               class="org.eclipse.core.resources.IResource">
118
               class="org.eclipse.core.resources.IResource">
112
         </selection>
119
         </selection>
113
      </wizard>
120
      </wizard>
121
      <wizard
122
            category="org.eclipse.ui.Basic"
123
            class="org.eclipse.ui.internal.wizards.projectmigration.ProjectMigrationExportWizard"
124
            icon="$nl$/icons/full/etool16/newprj_wiz.gif"
125
            id="org.eclipse.ui.wizards.export.ProjectMigrationExport"
126
            name="%ExportWizards.ProjectMigrationExport">
127
         <selection
128
               class="org.eclipse.core.resources.IProject">
129
         </selection>
130
         <description>
131
            %ExportWizards.ProjectMigrationDescription
132
         </description>
133
      </wizard>
114
   </extension>
134
   </extension>
115
   <extension
135
   <extension
116
         point="org.eclipse.ui.ide.markerImageProviders">
136
         point="org.eclipse.ui.ide.markerImageProviders">
(-)src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationOperation.java (+105 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006, 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Wind River Systems, Inc. - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.wizards.projectmigration;
12
13
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
14
15
import org.eclipse.core.resources.projectmigration.ProjectMigration;
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.core.runtime.IPath;
18
import org.eclipse.core.runtime.IProgressMonitor;
19
import org.eclipse.core.runtime.IStatus;
20
import org.eclipse.core.runtime.Status;
21
22
import org.eclipse.ui.dialogs.IOverwriteQuery;
23
24
import org.eclipse.ui.actions.WorkspaceModifyOperation;
25
26
/**
27
 * An operation which does the actual work of importing a migrated project into
28
 * the workspace.
29
 * <p>
30
 * This class may be instantiated; it is not intended to be subclassed.
31
 * </p>
32
 */
33
public class ProjectMigrationOperation extends WorkspaceModifyOperation {
34
35
	private IPath sourcePath;
36
37
	private IPath destinationPath;
38
39
	private String newProjectName;
40
41
	private String oldLinkedPathPrefix;
42
43
	private String newLinkedPathPrefix;
44
45
	//private boolean ignoreIndex;
46
47
	//private boolean ignoreFileInfo;
48
49
	protected IOverwriteQuery overwriteCallback;
50
51
	/**
52
	 * Creates a new operation that performs a "trusted import" of the specified
53
	 * project. This means that the file stat information and the PDOM from the
54
	 * source project are to be imported and trusted, i.e., not verified.
55
	 * <p>
56
	 * The <code>sourceObject</code> parameter represents the directory
57
	 * containing the project to import.
58
	 * </p>
59
	 * @param destinationPath
60
	 *            full path of destination directory
61
	 * @param sourcePath
62
	 *            file system object for project to import
63
	 * @param newProjName 
64
	 * @param oldLinkedPathPrefix 
65
	 * @param newLinkedPathPrefix 
66
	 */
67
	public ProjectMigrationOperation(IPath sourcePath, 
68
			String newProjName, IPath destinationPath, 
69
			String oldLinkedPathPrefix,	String newLinkedPathPrefix ) {
70
		super();
71
		this.sourcePath = sourcePath;
72
		this.destinationPath = destinationPath;
73
		this.newProjectName = newProjName;
74
		this.oldLinkedPathPrefix = oldLinkedPathPrefix;
75
		this.newLinkedPathPrefix = newLinkedPathPrefix;
76
		//this.ignoreIndex = ignoreIndex;
77
		//this.ignoreFileInfo = ignoreFileInfo;
78
	}
79
80
	/*
81
	 * (non-Javadoc) Method declared on WorkbenchModifyOperation. Imports the
82
	 * specified project from the file system.
83
	 */
84
	protected void execute(IProgressMonitor monitor) throws CoreException {
85
		ProjectMigration pm = new ProjectMigration( sourcePath, newProjectName, destinationPath);
86
87
		pm.setLinkedPathPrefix(oldLinkedPathPrefix, newLinkedPathPrefix);
88
		//pm.setIgnoreIndex(ignoreIndex);
89
		//pm.setIgnoreFileInfo(ignoreFileInfo);
90
91
		try {
92
			monitor
93
					.beginTask(
94
							Messages.getString("ProjectMigrationOperation.0"), //$NON-NLS-1$
95
							100);
96
			pm.execute(monitor);
97
		} catch (Exception e) {
98
			throw new CoreException(new Status(IStatus.ERROR,
99
					IDEWorkbenchPlugin.IDE_WORKBENCH, 0, Messages.getString("ProjectMigrationOperation.1"), e)); //$NON-NLS-1$
100
		} finally {
101
			monitor.done();
102
		}
103
	}
104
105
}
(-)src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationExportWizard.java (+62 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 Wind River Systems, Inc. and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Markus Schorn - initial API and implementation
10
 *******************************************************************************/ 
11
12
package org.eclipse.ui.internal.wizards.projectmigration;
13
14
import org.eclipse.jface.dialogs.IDialogSettings;
15
import org.eclipse.jface.viewers.IStructuredSelection;
16
import org.eclipse.jface.wizard.Wizard;
17
import org.eclipse.ui.IExportWizard;
18
import org.eclipse.ui.IWorkbench;
19
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
20
import org.eclipse.ui.internal.wizards.projectmigration.Messages;
21
22
/**
23
 * @since 3.4
24
 *
25
 */
26
public class ProjectMigrationExportWizard extends Wizard implements IExportWizard {
27
	private static final String DIALOG_SETTINGS_SECTION = "ProjectMigrationExportWizard"; //$NON-NLS-1$
28
	private ProjectMigrationExportWizardPage fMainPage;
29
	private IStructuredSelection fSelection;
30
31
	/**
32
	 * 
33
	 */
34
	public ProjectMigrationExportWizard() {
35
        IDialogSettings workbenchSettings = IDEWorkbenchPlugin.getDefault().getDialogSettings();
36
        IDialogSettings section = workbenchSettings.getSection(DIALOG_SETTINGS_SECTION);
37
        if (section == null) {
38
			section = workbenchSettings.addNewSection(DIALOG_SETTINGS_SECTION);
39
		}
40
        setDialogSettings(section);
41
	}
42
43
    //@Override
44
	public void addPages() {
45
        super.addPages();
46
        fMainPage = new ProjectMigrationExportWizardPage(fSelection);
47
        addPage(fMainPage);
48
    }
49
50
	//@Override
51
	public boolean performFinish() {
52
        return fMainPage.finish();
53
    }
54
55
	public void init(IWorkbench workbench, IStructuredSelection selection) {
56
        fSelection= selection;
57
        setWindowTitle(Messages.getString("ProjectMigrationExportWizard.0")); //$NON-NLS-1$
58
        setDefaultPageImageDescriptor(IDEWorkbenchPlugin.getIDEImageDescriptor("wizban/exportzip_wiz.png")); //$NON-NLS-1$
59
        setNeedsProgressMonitor(true);
60
	}
61
62
}
(-)src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationWizard.java (+108 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.wizards.projectmigration;
12
13
import org.eclipse.jface.dialogs.IDialogSettings;
14
import org.eclipse.jface.viewers.IStructuredSelection;
15
import org.eclipse.jface.wizard.Wizard;
16
import org.eclipse.ui.IImportWizard;
17
import org.eclipse.ui.IWorkbench;
18
//import org.eclipse.ui.internal.WorkbenchImages;
19
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
20
21
22
23
//import org.eclipse.cdt.internal.ui.CPluginImages;
24
//import org.eclipse.cdt.internal.ui.wizards.projectmigration.ProjectMigrationMessages;
25
//import org.eclipse.cdt.internal.ui.wizards.projectmigration.WizardProjectsMigrationPage;
26
27
/**
28
 * Standard workbench wizard for importing projects defined outside of the
29
 * currently defined projects into Eclipse.
30
 * <p>
31
 * This class may be instantiated and used without further configuration; this
32
 * class is not intended to be subclassed.
33
 * </p>
34
 * <p>
35
 * Example:
36
 * 
37
 * <pre>
38
 * IWizard wizard = new ProjectMigrationWizard();
39
 * wizard.init(workbench, selection);
40
 * WizardDialog dialog = new WizardDialog(shell, wizard);
41
 * dialog.open();
42
 * </pre>
43
 * 
44
 * During the call to <code>open</code>, the wizard dialog is presented to the
45
 * user. When the user hits Finish, a project is created with the location
46
 * specified by the user.
47
 * </p>
48
 */
49
50
public class ProjectMigrationWizard extends Wizard implements
51
		IImportWizard {
52
	private static final String EXTERNAL_PROJECT_SECTION = "ProjectMigrationWizard";//$NON-NLS-1$
53
	private ProjectMigrationWizardPage mainPage;
54
55
	/**
56
	 * Constructor for ProjectMigrationWizard.
57
	 */
58
	public ProjectMigrationWizard() {
59
		super();
60
		setNeedsProgressMonitor(true);
61
		IDialogSettings workbenchSettings = IDEWorkbenchPlugin.getDefault()
62
				.getDialogSettings();
63
64
		IDialogSettings wizardSettings = workbenchSettings
65
				.getSection(EXTERNAL_PROJECT_SECTION);
66
		if (wizardSettings == null) {
67
			wizardSettings = workbenchSettings
68
					.addNewSection(EXTERNAL_PROJECT_SECTION);
69
		}
70
		setDialogSettings(wizardSettings);
71
	}
72
73
	/*
74
	 * (non-Javadoc) Method declared on IWizard.
75
	 */
76
	public void addPages() {
77
		super.addPages();
78
		mainPage = new ProjectMigrationWizardPage();
79
		addPage(mainPage);
80
	}
81
82
	/*
83
	 * (non-Javadoc) Method declared on IWorkbenchWizard.
84
	 */
85
	public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
86
		setWindowTitle(Messages.getString("ProjectMigrationWizard.0")); //$NON-NLS-1$
87
		setDefaultPageImageDescriptor(IDEWorkbenchPlugin.getIDEImageDescriptor("wizban/importproj_wiz.png")); //$NON-NLS-1$
88
		//setDefaultPageImageDescriptor(WorkbenchImages.DESC_WIZBAN_MIGRATEPROJ);
89
		//				CUIPlugin.getIDEImageDescriptor("wizban/importproj_wiz.png")); //$NON-NLS-1$
90
91
	}
92
93
	/*
94
	 * (non-Javadoc) Method declared on IWizard.
95
	 */
96
	public boolean performCancel() {
97
		mainPage.performCancel();
98
		return true;
99
	}
100
101
	/*
102
	 * (non-Javadoc) Method declared on IWizard.
103
	 */
104
	public boolean performFinish() {
105
		return mainPage.createProjects();
106
	}
107
108
}
(-)src/org/eclipse/ui/internal/wizards/projectmigration/Messages.java (+44 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 Wind River Systems, Inc. and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Markus Schorn - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.ui.internal.wizards.projectmigration;
13
14
import java.util.MissingResourceException;
15
import java.util.ResourceBundle;
16
17
/**
18
 * @since 3.4
19
 *
20
 */
21
public class Messages  {
22
	private static final String BUNDLE_NAME = "org.eclipse.ui.internal.wizards.projectmigration.messages"; //$NON-NLS-1$
23
24
	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
25
26
	private Messages() {
27
		/*
28
		 * no initialization needed
29
		 */
30
	}
31
32
	/**
33
	 * @param key
34
	 * @return a String corresponding to the key.
35
	 */
36
	public static String getString(String key) {
37
		try {
38
			return RESOURCE_BUNDLE.getString(key);
39
		} catch (MissingResourceException e) {
40
			return '!' + key + '!';
41
		}
42
	}
43
44
}
(-)src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationExportWizardPage.java (+385 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Markus Schorn - initial API and implementation
10
 *******************************************************************************/ 
11
package org.eclipse.ui.internal.wizards.projectmigration;
12
13
import java.lang.reflect.InvocationTargetException;
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.List;
19
20
import org.eclipse.core.resources.IProject;
21
import org.eclipse.core.resources.projectmigration.ExportProjectMigrationInfo;
22
23
import org.eclipse.core.runtime.CoreException;
24
import org.eclipse.core.runtime.IProgressMonitor;
25
import org.eclipse.core.runtime.MultiStatus;
26
import org.eclipse.core.runtime.SubProgressMonitor;
27
28
import org.eclipse.jface.dialogs.ErrorDialog;
29
import org.eclipse.jface.dialogs.IDialogConstants;
30
import org.eclipse.jface.operation.IRunnableWithProgress;
31
import org.eclipse.jface.viewers.CheckStateChangedEvent;
32
import org.eclipse.jface.viewers.CheckboxTableViewer;
33
import org.eclipse.jface.viewers.ICheckStateListener;
34
import org.eclipse.jface.viewers.IStructuredContentProvider;
35
import org.eclipse.jface.viewers.IStructuredSelection;
36
import org.eclipse.jface.viewers.Viewer;
37
38
import org.eclipse.swt.SWT;
39
import org.eclipse.swt.events.SelectionAdapter;
40
import org.eclipse.swt.events.SelectionEvent;
41
import org.eclipse.swt.graphics.Font;
42
import org.eclipse.swt.layout.GridData;
43
import org.eclipse.swt.layout.GridLayout;
44
import org.eclipse.swt.widgets.Button;
45
import org.eclipse.swt.widgets.Composite;
46
import org.eclipse.swt.widgets.Event;
47
import org.eclipse.swt.widgets.Label;
48
import org.eclipse.swt.widgets.Shell;
49
import org.eclipse.swt.widgets.Table;
50
import org.eclipse.ui.dialogs.WizardDataTransferPage;
51
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
52
import org.eclipse.ui.internal.wizards.projectmigration.Messages;
53
import org.eclipse.ui.model.WorkbenchLabelProvider;
54
55
56
 
57
/**
58
 * @since 3.4
59
 *
60
 */
61
public class ProjectMigrationExportWizardPage extends  WizardDataTransferPage {
62
63
    private IStructuredSelection fInitialSelection;
64
	private CheckboxTableViewer fProjectViewer;
65
66
67
    /**
68
     *	Create an instance of this class
69
     */
70
    protected ProjectMigrationExportWizardPage(String name, IStructuredSelection selection) {
71
        super(name);
72
        fInitialSelection= selection;
73
    }
74
75
    /**
76
     * Create an instance of this class.
77
     *
78
     * @param selection the selection
79
     */
80
    public ProjectMigrationExportWizardPage(IStructuredSelection selection) {
81
        this("indexExportPage", selection); //$NON-NLS-1$
82
        setTitle(Messages.getString("ProjectMigrationExportWizardPage.0"));  //$NON-NLS-1$
83
        setDescription(Messages.getString("ProjectMigrationExportWizardPage.1"));  //$NON-NLS-1$
84
    }
85
86
    public void createControl(Composite parent) {
87
        initializeDialogUnits(parent);
88
89
        Composite composite = new Composite(parent, SWT.NULL);
90
        composite.setLayout(new GridLayout());
91
        composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
92
                | GridData.HORIZONTAL_ALIGN_FILL));
93
        composite.setFont(parent.getFont());
94
95
        createResourcesGroup(composite);
96
        createDestinationGroup(composite);
97
        createOptionsArea(composite);
98
99
        restoreWidgetValues(); 
100
        if (fInitialSelection != null) {
101
			setupBasedOnInitialSelections();
102
		}
103
        //setupDestination();
104
105
        updateWidgetEnablements();
106
        setPageComplete(determinePageCompletion());
107
        setErrorMessage(null);	// should not initially have error message
108
        
109
        setControl(composite);
110
    }
111
112
    /**
113
     * Creates the checkbox tree and list for selecting resources.
114
     *
115
     * @param parent the parent control
116
     */
117
    private final void createResourcesGroup(Composite parent) {
118
        Composite resourcesGroup = new Composite(parent, SWT.NONE);
119
        resourcesGroup.setLayout(new GridLayout());
120
        resourcesGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
121
        resourcesGroup.setFont(parent.getFont());
122
123
        new Label(resourcesGroup, SWT.NONE).setText(Messages.getString("ProjectMigrationExportWizardPage.2"));        //$NON-NLS-1$
124
        Table table= new Table(resourcesGroup, SWT.CHECK | SWT.BORDER);
125
        table.setLayoutData(new GridData(GridData.FILL_BOTH));
126
		fProjectViewer= new CheckboxTableViewer(table);
127
		fProjectViewer.setContentProvider(new IStructuredContentProvider() {
128
			List fContents;	
129
130
			public Object[] getElements(Object input) {
131
				if (fContents != null && fContents == input)
132
					return fContents.toArray();
133
				return new Object[0];
134
			}
135
136
			public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
137
				if (newInput instanceof List) 
138
					fContents= (List)newInput;
139
				else
140
					fContents= null;
141
				// we use a fixed set.
142
			}
143
144
			public void dispose() {
145
			}
146
			
147
148
		} );
149
		fProjectViewer.setLabelProvider(new WorkbenchLabelProvider());        
150
        ICheckStateListener checkListener = new ICheckStateListener() {
151
            public void checkStateChanged(CheckStateChangedEvent event) {
152
                updateWidgetEnablements();
153
            }
154
        };
155
        fProjectViewer.addCheckStateListener(checkListener);
156
        	
157
158
        // top level group
159
        Composite buttonComposite = new Composite(resourcesGroup, SWT.NONE);
160
        buttonComposite.setFont(parent.getFont());
161
162
        GridLayout layout = new GridLayout(2, true);
163
        layout.marginHeight= layout.marginWidth= 0;
164
        buttonComposite.setLayout(layout);
165
        buttonComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
166
                | GridData.HORIZONTAL_ALIGN_FILL));
167
168
169
        Button selectButton = createButton(buttonComposite,
170
                IDialogConstants.SELECT_ALL_ID, Messages.getString("ProjectMigrationExportWizardPage.3"), false); //$NON-NLS-1$
171
172
        SelectionAdapter listener = new SelectionAdapter() {
173
            //@Override
174
			public void widgetSelected(SelectionEvent e) {
175
                fProjectViewer.setAllChecked(true);
176
                updateWidgetEnablements();
177
            }
178
        };
179
        selectButton.addSelectionListener(listener);
180
181
        Button deselectButton = createButton(buttonComposite,
182
                IDialogConstants.DESELECT_ALL_ID, Messages.getString("ProjectMigrationExportWizardPage.4"), false); //$NON-NLS-1$
183
184
        listener = new SelectionAdapter() {
185
            //@Override
186
			public void widgetSelected(SelectionEvent e) {
187
            	fProjectViewer.setAllChecked(false);
188
                updateWidgetEnablements();
189
            }
190
        };
191
        deselectButton.addSelectionListener(listener);
192
193
        initProjects();
194
    }
195
196
    private Button createButton(Composite parent, int id, String label,
197
            boolean defaultButton) {
198
        Button button = new Button(parent, SWT.PUSH);
199
200
        GridData buttonData = new GridData(GridData.FILL_HORIZONTAL);
201
        button.setLayoutData(buttonData);
202
203
        button.setData(new Integer(id));
204
        button.setText(label);
205
        button.setFont(parent.getFont());
206
207
        if (defaultButton) {
208
            Shell shell = parent.getShell();
209
            if (shell != null) {
210
                shell.setDefaultButton(button);
211
            }
212
            button.setFocus();
213
        }
214
        button.setFont(parent.getFont());
215
        setButtonLayoutData(button);
216
        return button;
217
    }
218
219
    private void initProjects() {
220
        ArrayList input = new ArrayList();
221
        IProject[] projects;
222
		projects = IDEWorkbenchPlugin.getPluginWorkspace().getRoot().getProjects();
223
			for (int i = 0; i < projects.length; i++) {
224
				if (projects[i].isOpen()) {
225
					input.add(projects[i]);
226
				}
227
	        }
228
		fProjectViewer.setInput(input);
229
	}
230
231
    private void setupBasedOnInitialSelections() {
232
    	HashSet names= new HashSet();
233
        Iterator it = fInitialSelection.iterator();
234
        while (it.hasNext()) {
235
            IProject project = (IProject) it.next();
236
            names.add(project.getName());
237
        }
238
        
239
        Collection prjsc= (Collection) fProjectViewer.getInput();
240
        Object[] prjs= prjsc.toArray();
241
        for (int i = 0; i < prjs.length; i++) {
242
        	Object element = prjs[i];
243
			IProject prj = (IProject) element;
244
			if (names.contains(prj.getName())) {
245
	            fProjectViewer.setChecked(prj, true);
246
			}
247
		}
248
    }
249
    
250
251
  	
252
    
253
    private void createDestinationGroup(Composite parent) {
254
    	Font font = parent.getFont();
255
        // destination specification group
256
        Composite destinationSelectionGroup = new Composite(parent, SWT.NONE);
257
        destinationSelectionGroup.setLayout(new GridLayout(2, false));
258
        destinationSelectionGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
259
        destinationSelectionGroup.setFont(font);
260
261
262
    }
263
264
	/**
265
	 * Create the area with the extra options.
266
	 * 
267
	 * @param workArea
268
	 */
269
	private void createOptionsArea(Composite workArea) {
270
		Composite optionsGroup = new Composite(workArea, SWT.NONE);
271
		optionsGroup.setLayout(new GridLayout());
272
		optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
273
274
	}
275
276
277
	/**
278
	 * @return Return true to indicate that the operation was a success
279
	 * 
280
	 */
281
	public boolean finish() {
282
        IProject[] projectsToExport= getCheckedElements();
283
284
        // about to invoke the operation so save our state
285
        saveWidgetValues();
286
        
287
        return executeExportOperation(projectsToExport);
288
    }
289
290
	private IProject[] getCheckedElements() {
291
		Object[] obj= fProjectViewer.getCheckedElements();
292
		IProject[] prjs= new IProject[obj.length];
293
		System.arraycopy(obj, 0, prjs, 0, obj.length);
294
		return prjs;
295
	}
296
297
    private boolean executeExportOperation(final IProject[] projects) {
298
    	//final String dest= getDestinationValue();
299
    	final MultiStatus status= new MultiStatus(IDEWorkbenchPlugin.IDE_WORKBENCH, 
300
    			0, Messages.getString("ProjectMigrationExportWizardPage.5"), null);  //$NON-NLS-1$
301
    			
302
    	IRunnableWithProgress op= new IRunnableWithProgress() {
303
			/**
304
			 * @throws InvocationTargetException 
305
			 * @throws InterruptedException  
306
			 */
307
			public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
308
				monitor.beginTask("", projects.length); //$NON-NLS-1$
309
				for( int i = 0; i < projects.length; i++ ) {
310
					IProject project = projects[i];
311
					ExportProjectMigrationInfo op = new ExportProjectMigrationInfo( project );
312
313
					try {
314
						op.run(new SubProgressMonitor(monitor, 1));
315
					} catch (CoreException e) {
316
						status.merge(e.getStatus());
317
					}
318
				}
319
			}
320
    	};
321
        try {
322
            getContainer().run(true, true, op);
323
        } catch (InterruptedException e) {
324
            return false;
325
        } catch (InvocationTargetException e) {
326
            IDEWorkbenchPlugin.log(Messages.getString("ProjectMigrationExportWizardPage.5"), //$NON-NLS-1$
327
            		e.getTargetException());
328
            displayErrorDialog(e.getTargetException());
329
            return false;
330
        }
331
332
        if (!status.isOK()) {
333
        	IDEWorkbenchPlugin.log("",status); //$NON-NLS-1$
334
            ErrorDialog.openError(getContainer().getShell(),
335
                    getErrorDialogTitle(),
336
                    null, // no special message
337
                    status);
338
            return false;
339
        }
340
341
        return true;
342
    }
343
344
345
346
 
347
    //@Override
348
	protected boolean validateSourceGroup() {
349
    	// there must be some resources selected for Export
350
    	boolean isValid = true;
351
        Object[] projectsToExport = getCheckedElements();
352
    	if (projectsToExport.length == 0){
353
    		setErrorMessage(Messages.getString("ProjectMigrationExportWizardPage.7"));  //$NON-NLS-1$
354
            isValid =  false;
355
    	} else {
356
			setErrorMessage(null);
357
		}
358
		return super.validateSourceGroup() && isValid;
359
	}
360
361
    //@Override
362
	protected void updateWidgetEnablements() {
363
        boolean pageComplete = determinePageCompletion();
364
        setPageComplete(pageComplete);
365
        if (pageComplete) {
366
			setMessage(null);
367
		}
368
        super.updateWidgetEnablements();
369
    }
370
    
371
372
	public void handleEvent(Event event) {
373
		updateWidgetEnablements();
374
	}
375
	
376
    //@Override
377
	protected String getErrorDialogTitle() {
378
        return Messages.getString("ProjectMigrationExportWizardPage.8");  //$NON-NLS-1$
379
    }
380
381
	//@Override
382
	protected boolean allowNewContainerName() {
383
		return false;
384
	}
385
}
(-)src/org/eclipse/ui/internal/wizards/projectmigration/ProjectMigrationWizardPage.java (+1151 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004, 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *     Red Hat, Inc - extensive changes to allow importing of Archive Files
11
 *     Philippe Ombredanne (pombredanne@nexb.com)
12
 *     		- Bug 101180 [Import/Export] Import Existing Project into Workspace default widget is back button , should be text field
13
 *     Martin Oberhuber (martin.oberhuber@windriver.com)
14
 *     		- Bug 187318[Wizards] "Import Existing Project" loops forever with cyclic symbolic links
15
 *     Remy Chi Jian Suen  (remy.suen@gmail.com)
16
 *     		- Bug 210568 [Import/Export] [Import/Export] - Refresh button does not update list of projects
17
 *******************************************************************************/
18
package org.eclipse.ui.internal.wizards.projectmigration;
19
20
import java.io.*;
21
import java.lang.reflect.InvocationTargetException;
22
import java.util.ArrayList;
23
import java.util.Collection;
24
import java.util.HashSet;
25
import java.util.Iterator;
26
import java.util.List;
27
import java.util.Set;
28
29
import org.eclipse.core.resources.IProject;
30
import org.eclipse.core.resources.IProjectDescription;
31
import org.eclipse.core.runtime.CoreException;
32
import org.eclipse.core.runtime.IPath;
33
import org.eclipse.core.runtime.IProgressMonitor;
34
import org.eclipse.core.runtime.IStatus;
35
import org.eclipse.core.runtime.OperationCanceledException;
36
import org.eclipse.core.runtime.Path;
37
import org.eclipse.core.runtime.Platform;
38
import org.eclipse.core.runtime.Status;
39
import org.eclipse.core.runtime.SubProgressMonitor;
40
import org.eclipse.jface.dialogs.Dialog;
41
import org.eclipse.jface.dialogs.ErrorDialog;
42
import org.eclipse.jface.dialogs.IDialogConstants;
43
import org.eclipse.jface.dialogs.IDialogSettings;
44
import org.eclipse.jface.dialogs.MessageDialog;
45
import org.eclipse.jface.operation.IRunnableWithProgress;
46
import org.eclipse.jface.viewers.CheckStateChangedEvent;
47
import org.eclipse.jface.viewers.CheckboxTreeViewer;
48
import org.eclipse.jface.viewers.ICheckStateListener;
49
import org.eclipse.jface.viewers.ITreeContentProvider;
50
import org.eclipse.jface.viewers.LabelProvider;
51
import org.eclipse.jface.viewers.Viewer;
52
import org.eclipse.jface.viewers.ViewerComparator;
53
import org.eclipse.jface.wizard.WizardPage;
54
import org.eclipse.osgi.util.NLS;
55
import org.eclipse.swt.SWT;
56
import org.eclipse.swt.events.FocusAdapter;
57
import org.eclipse.swt.events.SelectionAdapter;
58
import org.eclipse.swt.events.SelectionEvent;
59
import org.eclipse.swt.events.TraverseEvent;
60
import org.eclipse.swt.events.TraverseListener;
61
import org.eclipse.swt.layout.GridData;
62
import org.eclipse.swt.layout.GridLayout;
63
import org.eclipse.swt.widgets.Button;
64
import org.eclipse.swt.widgets.Composite;
65
import org.eclipse.swt.widgets.DirectoryDialog;
66
import org.eclipse.swt.widgets.Label;
67
import org.eclipse.swt.widgets.Text;
68
69
//import org.eclipse.cdt.core.CCorePlugin;
70
//import org.eclipse.cdt.ui.CUIPlugin;
71
72
import org.eclipse.ui.actions.WorkspaceModifyOperation;
73
74
import org.eclipse.ui.dialogs.IOverwriteQuery;
75
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
76
import org.eclipse.ui.statushandlers.StatusManager;
77
78
/**
79
 * The ProjectMigrationWizardPage is the page that allows the user to import
80
 * projects from a particular location.
81
 */
82
public class ProjectMigrationWizardPage extends WizardPage implements
83
		IOverwriteQuery {
84
85
	/**
86
	 * The name of the folder containing metadata information for the workspace.
87
	 */
88
	public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$
89
90
	/**
91
	 * Class declared public only for test suite.
92
	 * 
93
	 */
94
	public class ProjectRecord {
95
		File projectSystemFile;
96
97
		String projectName;
98
99
		Object parent;
100
101
		int level;
102
103
		IProjectDescription description;
104
105
		/**
106
		 * Create a record for a project based on the info in the file.
107
		 * 
108
		 * @param file
109
		 */
110
		ProjectRecord(File file) {
111
			projectSystemFile = file;
112
			setProjectName();
113
		}
114
115
		/**
116
		 * Set the name of the project based on the projectFile.
117
		 */
118
		private void setProjectName() {
119
			try {
120
121
				// If we don't have the project name try again
122
				if (projectName == null) {
123
					IPath path = new Path(projectSystemFile.getPath());
124
					// if the file is in the default location, use the directory
125
					// name as the project name
126
					if (isDefaultLocation(path)) {
127
						projectName = path.segment(path.segmentCount() - 2);
128
						description = IDEWorkbenchPlugin.getPluginWorkspace()
129
								.newProjectDescription(projectName);
130
					} else {
131
						description = IDEWorkbenchPlugin.getPluginWorkspace()
132
								.loadProjectDescription(path);
133
						projectName = description.getName();
134
					}
135
136
				}
137
			} catch (CoreException e) {
138
				// no good couldn't get the name
139
			}
140
		}
141
142
		/**
143
		 * Returns whether the given project description file path is in the
144
		 * default location for a project
145
		 * 
146
		 * @param path
147
		 *            The path to examine
148
		 * @return Whether the given path is the default location for a project
149
		 */
150
		private boolean isDefaultLocation(IPath path) {
151
			// The project description file must at least be within the project,
152
			// which is within the workspace location
153
			if (path.segmentCount() < 2)
154
				return false;
155
			return path.removeLastSegments(2).toFile().equals(
156
					Platform.getLocation().toFile());
157
		}
158
159
		/**
160
		 * Get the name of the project
161
		 * 
162
		 * @return String
163
		 */
164
		public String getProjectName() {
165
			return projectName;
166
		}
167
168
		/**
169
		 * Gets the label to be used when rendering this project record in the
170
		 * UI.
171
		 * 
172
		 * @return String the label
173
		 * @since 3.4
174
		 */
175
		public String getProjectLabel() {
176
			if (description == null)
177
				return projectName;
178
179
			String path = projectSystemFile.getParent();
180
181
			return NLS
182
					.bind(
183
							Messages.getString("ProjectMigrationWizardPage.0"), //$NON-NLS-1$
184
							projectName, path);
185
		}
186
	}
187
188
	// dialog store id constants
189
	//private final static String STORE_IGNORE_EXPORTED_INDEX_ID = "ProjectMigrationWizardPage.STORE_IGNORE_EXPORTED_INDEX_ID"; //$NON-NLS-1$
190
191
	//private final static String STORE_IGNORE_EXPORTED_PROJECT_ID = "ProjectMigrationWizardPage.STORE_IGNORE_EXPORTED_PROJECT_ID"; //$NON-NLS-1$
192
193
	//private final static String STORE_SHOW_TIMING_PROJECT_ID = "ProjectMigrationWizardPage.STORE_SHOW_TIMING_PROJECT_ID"; //$NON-NLS-1$
194
195
	private Text directoryPathField;
196
197
	private Text directoryDestinationPathField;
198
199
	private Text newProjectNameField;
200
201
	private Text oldLinkedPathPrefixField;
202
203
	private Text newLinkedPathPrefixField;
204
205
	private CheckboxTreeViewer projectsList;
206
207
	//private Button ignoreExportedIndexCheckbox;
208
209
	//private Button ignoreExportedProjectRefreshCheckBox;
210
211
	//private Button showTimingCheckBox;
212
213
	//private boolean ignoreExportedIndex = false;
214
215
	//private boolean ignoreExportedProjectRefresh = false;
216
217
	//private boolean showTiming = false;
218
219
	private ProjectRecord[] selectedProjects = new ProjectRecord[0];
220
221
	// Keep track of the directory that we browsed to last time
222
	// the wizard was invoked.
223
	private static String previouslyBrowsedDirectory = ""; //$NON-NLS-1$
224
225
	private static String previouslyBrowsedDestinationDirectory = ""; //$NON-NLS-1$
226
227
	private Button browseDirectoriesButton;
228
229
	private Button browseDestinationDirectoryButton;
230
231
	private IProject[] wsProjects;
232
233
	// The last selected path to minimize searches
234
	private String lastPath;
235
236
	// The last time that the file or folder at the selected path was modified
237
	// to mimize searches
238
	private long lastModified;
239
240
	/**
241
	 * Creates a new project creation wizard page.
242
	 * 
243
	 */
244
	public ProjectMigrationWizardPage() {
245
		this("wizardExternalProjectsPage"); //$NON-NLS-1$
246
	}
247
248
	/**
249
	 * Create a new instance of the receiver.
250
	 * 
251
	 * @param pageName
252
	 */
253
	public ProjectMigrationWizardPage(String pageName) {
254
		super(pageName);
255
		setPageComplete(false);
256
		setTitle(Messages.getString("ProjectMigrationWizardPage.1")); //$NON-NLS-1$
257
		setDescription(Messages.getString("ProjectMigrationWizardPage.2")); //$NON-NLS-1$
258
	}
259
260
	/*
261
	 * (non-Javadoc)
262
	 * 
263
	 * @see
264
	 * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets
265
	 * .Composite)
266
	 */
267
	public void createControl(Composite parent) {
268
269
		initializeDialogUnits(parent);
270
271
		Composite workArea = new Composite(parent, SWT.NONE);
272
		setControl(workArea);
273
274
		workArea.setLayout(new GridLayout());
275
		workArea.setLayoutData(new GridData(GridData.FILL_BOTH
276
				| GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL));
277
278
		createProjectsRoot(workArea);
279
		createProjectsList(workArea);
280
		createLinkedPathPrefixArea(workArea);
281
		createDestinationArea(workArea);
282
		createOptionsArea(workArea);
283
		restoreWidgetValues();
284
		Dialog.applyDialogFont(workArea);
285
286
	}
287
288
	/**
289
	 * Create the area with the extra options.
290
	 * 
291
	 * @param workArea
292
	 */
293
	private void createOptionsArea(Composite workArea) {
294
		Composite optionsGroup = new Composite(workArea, SWT.NONE);
295
		optionsGroup.setLayout(new GridLayout());
296
		optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
297
298
	}
299
300
	private void checkForComplete() {
301
		if (projectsList.getCheckedElements().length == 1) {
302
			String path = directoryDestinationPathField.getText().trim();
303
			if (path.length() > 0) {
304
				File dirpath = new File(path);
305
				if (dirpath.exists()) {
306
					setPageComplete(true);
307
					return;
308
				}
309
			}
310
		}
311
312
		setPageComplete(false);
313
	}
314
315
	/**
316
	 * Create the checkbox list for the found projects.
317
	 * 
318
	 * @param workArea
319
	 */
320
	private void createProjectsList(Composite workArea) {
321
322
		Label title = new Label(workArea, SWT.NONE);
323
		title
324
				.setText(Messages.getString("ProjectMigrationWizardPage.3")); //$NON-NLS-1$
325
326
		Composite listComposite = new Composite(workArea, SWT.NONE);
327
		GridLayout layout = new GridLayout();
328
		layout.numColumns = 2;
329
		layout.marginWidth = 0;
330
		layout.makeColumnsEqualWidth = false;
331
		listComposite.setLayout(layout);
332
333
		listComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
334
				| GridData.GRAB_VERTICAL | GridData.FILL_BOTH));
335
336
		projectsList = new CheckboxTreeViewer(listComposite, SWT.BORDER);
337
		GridData listData = new GridData(GridData.GRAB_HORIZONTAL
338
				| GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
339
		listData.heightHint = 100;
340
		projectsList.getControl().setLayoutData(listData);
341
342
		projectsList.setContentProvider(new ITreeContentProvider() {
343
344
			/*
345
			 * (non-Javadoc)
346
			 * 
347
			 * @see
348
			 * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java
349
			 * .lang.Object)
350
			 */
351
			public Object[] getChildren(Object parentElement) {
352
				return null;
353
			}
354
355
			/*
356
			 * (non-Javadoc)
357
			 * 
358
			 * @see
359
			 * org.eclipse.jface.viewers.IStructuredContentProvider#getElements
360
			 * (java.lang.Object)
361
			 */
362
			public Object[] getElements(Object inputElement) {
363
				return getValidProjects();
364
			}
365
366
			/*
367
			 * (non-Javadoc)
368
			 * 
369
			 * @see
370
			 * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java
371
			 * .lang.Object)
372
			 */
373
			public boolean hasChildren(Object element) {
374
				return false;
375
			}
376
377
			/*
378
			 * (non-Javadoc)
379
			 * 
380
			 * @see
381
			 * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java
382
			 * .lang.Object)
383
			 */
384
			public Object getParent(Object element) {
385
				return null;
386
			}
387
388
			/*
389
			 * (non-Javadoc)
390
			 * 
391
			 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
392
			 */
393
			public void dispose() {
394
395
			}
396
397
			/*
398
			 * (non-Javadoc)
399
			 * 
400
			 * @see
401
			 * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse
402
			 * .jface.viewers.Viewer, java.lang.Object, java.lang.Object)
403
			 */
404
			public void inputChanged(Viewer viewer, Object oldInput,
405
					Object newInput) {
406
			}
407
408
		});
409
410
		projectsList.setLabelProvider(new LabelProvider() {
411
			/*
412
			 * (non-Javadoc)
413
			 * 
414
			 * @see
415
			 * org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
416
			 */
417
			public String getText(Object element) {
418
				return ((ProjectRecord) element).getProjectLabel();
419
			}
420
		});
421
422
		projectsList.addCheckStateListener(new ICheckStateListener() {
423
			/*
424
			 * (non-Javadoc)
425
			 * 
426
			 * @see
427
			 * org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged
428
			 * (org.eclipse.jface.viewers.CheckStateChangedEvent)
429
			 */
430
			public void checkStateChanged(CheckStateChangedEvent event) {
431
				checkForComplete();
432
			}
433
		});
434
435
		projectsList.setInput(this);
436
		projectsList.setComparator(new ViewerComparator());
437
	}
438
439
	/**
440
	 * Create the checkbox list for the found projects.
441
	 * 
442
	 * @param workArea
443
	 */
444
	private void createLinkedPathPrefixArea(Composite workArea) {
445
446
		// project specification group
447
		Composite projectGroup = new Composite(workArea, SWT.NONE);
448
		GridLayout layout = new GridLayout();
449
		layout.numColumns = 2;
450
		layout.makeColumnsEqualWidth = false;
451
		layout.marginWidth = 0;
452
		projectGroup.setLayout(layout);
453
		projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
454
455
		// old linked directory path
456
		Label oldLinkedPathLabel = new Label(projectGroup, SWT.NONE);
457
		oldLinkedPathLabel
458
				.setText(Messages.getString("ProjectMigrationWizardPage.4")); //$NON-NLS-1$
459
460
		this.oldLinkedPathPrefixField = new Text(projectGroup, SWT.BORDER);
461
462
		this.oldLinkedPathPrefixField.setLayoutData(new GridData(
463
				GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
464
465
		// new linked directory path
466
		Label newLinkedPathLabel = new Label(projectGroup, SWT.NONE);
467
		newLinkedPathLabel
468
				.setText(Messages.getString("ProjectMigrationWizardPage.5")); //$NON-NLS-1$
469
470
		this.newLinkedPathPrefixField = new Text(projectGroup, SWT.BORDER);
471
472
		this.newLinkedPathPrefixField.setLayoutData(new GridData(
473
				GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
474
475
	}
476
477
	/**
478
	 * Create the checkbox list for the found projects.
479
	 * 
480
	 * @param workArea
481
	 */
482
	private void createDestinationArea(Composite workArea) {
483
484
		// project specification group
485
		Composite projectGroup = new Composite(workArea, SWT.NONE);
486
		GridLayout layout = new GridLayout();
487
		layout.numColumns = 3;
488
		layout.makeColumnsEqualWidth = false;
489
		layout.marginWidth = 0;
490
		projectGroup.setLayout(layout);
491
		projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
492
493
		Label title = new Label(projectGroup, SWT.NONE);
494
		title
495
				.setText(Messages.getString("ProjectMigrationWizardPage.6")); //$NON-NLS-1$
496
497
		// project destination directory location entry field
498
		this.directoryDestinationPathField = new Text(projectGroup, SWT.BORDER);
499
500
		this.directoryDestinationPathField.setLayoutData(new GridData(
501
				GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
502
503
		// browse button
504
		browseDestinationDirectoryButton = new Button(projectGroup, SWT.PUSH);
505
		browseDestinationDirectoryButton
506
				.setText(Messages.getString("ProjectMigrationWizardPage.7")); //$NON-NLS-1$
507
		setButtonLayoutData(browseDestinationDirectoryButton);
508
509
		browseDestinationDirectoryButton
510
				.addSelectionListener(new SelectionAdapter() {
511
					/*
512
					 * (non-Javadoc)
513
					 * 
514
					 * @see org.eclipse.swt.events.SelectionAdapter#widgetS
515
					 * elected(org.eclipse.swt.events.SelectionEvent)
516
					 */
517
					public void widgetSelected(SelectionEvent e) {
518
						handleLocationDestinationDirectoryButtonPressed();
519
					}
520
				});
521
522
		directoryDestinationPathField
523
				.addTraverseListener(new TraverseListener() {
524
525
					/*
526
					 * (non-Javadoc)
527
					 * 
528
					 * @see
529
					 * org.eclipse.swt.events.TraverseListener#keyTraversed(
530
					 * org.eclipse.swt.events.TraverseEvent)
531
					 */
532
					public void keyTraversed(TraverseEvent e) {
533
						if (e.detail == SWT.TRAVERSE_RETURN) {
534
							e.doit = false;
535
							checkForComplete();
536
						}
537
					}
538
539
				});
540
541
		directoryDestinationPathField.addFocusListener(new FocusAdapter() {
542
543
			/*
544
			 * (non-Javadoc)
545
			 * 
546
			 * @see
547
			 * org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt
548
			 * .events.FocusEvent)
549
			 */
550
			public void focusLost(org.eclipse.swt.events.FocusEvent e) {
551
				checkForComplete();
552
			}
553
554
		});
555
556
		Label projectTitle = new Label(projectGroup, SWT.NONE);
557
		projectTitle
558
				.setText(Messages.getString("ProjectMigrationWizardPage.8")); //$NON-NLS-1$
559
560
		// project name location entry field
561
		this.newProjectNameField = new Text(projectGroup, SWT.BORDER);
562
563
		this.newProjectNameField.setLayoutData(new GridData(
564
				GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
565
	}
566
567
	/**
568
	 * Create the area where you select the root directory for the projects.
569
	 * 
570
	 * @param workArea
571
	 *            Composite
572
	 */
573
	private void createProjectsRoot(Composite workArea) {
574
575
		// project specification group
576
		Composite projectGroup = new Composite(workArea, SWT.NONE);
577
		GridLayout layout = new GridLayout();
578
		layout.numColumns = 3;
579
		layout.makeColumnsEqualWidth = false;
580
		layout.marginWidth = 0;
581
		projectGroup.setLayout(layout);
582
		projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
583
584
		Label dirTitle = new Label(projectGroup, SWT.NONE);
585
		dirTitle
586
				.setText(Messages.getString("ProjectMigrationWizardPage.9")); //$NON-NLS-1$
587
588
		// project location entry field
589
		this.directoryPathField = new Text(projectGroup, SWT.BORDER);
590
591
		this.directoryPathField.setLayoutData(new GridData(
592
				GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
593
594
		// browse button
595
		browseDirectoriesButton = new Button(projectGroup, SWT.PUSH);
596
		browseDirectoriesButton
597
				.setText(Messages.getString("ProjectMigrationWizardPage.10")); //$NON-NLS-1$
598
		setButtonLayoutData(browseDirectoriesButton);
599
600
		browseDirectoriesButton.addSelectionListener(new SelectionAdapter() {
601
			/*
602
			 * (non-Javadoc)
603
			 * 
604
			 * @see org.eclipse.swt.events.SelectionAdapter#widgetS
605
			 * elected(org.eclipse.swt.events.SelectionEvent)
606
			 */
607
			public void widgetSelected(SelectionEvent e) {
608
				handleLocationDirectoryButtonPressed();
609
			}
610
611
		});
612
613
		directoryPathField.addTraverseListener(new TraverseListener() {
614
615
			/*
616
			 * (non-Javadoc)
617
			 * 
618
			 * @see
619
			 * org.eclipse.swt.events.TraverseListener#keyTraversed(org.eclipse
620
			 * .swt.events.TraverseEvent)
621
			 */
622
			public void keyTraversed(TraverseEvent e) {
623
				if (e.detail == SWT.TRAVERSE_RETURN) {
624
					e.doit = false;
625
					updateProjectsList(directoryPathField.getText().trim());
626
				}
627
			}
628
629
		});
630
631
		directoryPathField.addFocusListener(new FocusAdapter() {
632
633
			/*
634
			 * (non-Javadoc)
635
			 * 
636
			 * @see
637
			 * org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt
638
			 * .events.FocusEvent)
639
			 */
640
			public void focusLost(org.eclipse.swt.events.FocusEvent e) {
641
				updateProjectsList(directoryPathField.getText().trim());
642
			}
643
644
		});
645
	}
646
647
	/*
648
	 * (non-Javadoc) Method declared on IDialogPage. Set the focus on path
649
	 * fields when page becomes visible.
650
	 */
651
	public void setVisible(boolean visible) {
652
		super.setVisible(visible);
653
		if (visible) {
654
			this.directoryPathField.setFocus();
655
		}
656
	}
657
658
	/**
659
	 * Update the list of projects based on path. Method declared public only
660
	 * for test suite.
661
	 * 
662
	 * @param path
663
	 */
664
	public void updateProjectsList(final String path) {
665
		// on an empty path empty selectedProjects
666
		if (path == null || path.length() == 0) {
667
			setMessage(Messages.getString("ProjectMigrationWizardPage.11")); //$NON-NLS-1$
668
			selectedProjects = new ProjectRecord[0];
669
			projectsList.refresh(true);
670
			projectsList.setCheckedElements(selectedProjects);
671
			checkForComplete();
672
			lastPath = path;
673
			return;
674
		}
675
676
		final File directory = new File(path);
677
		long modified = directory.lastModified();
678
		if (path.equals(lastPath) && lastModified == modified) {
679
			// since the file/folder was not modified and the path did not
680
			// change, no refreshing is required
681
			return;
682
		}
683
684
		lastPath = path;
685
		lastModified = modified;
686
687
		try {
688
			getContainer().run(true, true, new IRunnableWithProgress() {
689
690
				/*
691
				 * (non-Javadoc)
692
				 * 
693
				 * @see
694
				 * org.eclipse.jface.operation.IRunnableWithProgress#run(org
695
				 * .eclipse.core.runtime.IProgressMonitor)
696
				 */
697
				public void run(IProgressMonitor monitor) {
698
699
					boolean dirSelected = true;
700
701
					monitor
702
							.beginTask(
703
									Messages.getString("ProjectMigrationWizardPage.12"), //$NON-NLS-1$
704
									100);
705
					selectedProjects = new ProjectRecord[0];
706
					Collection files = new ArrayList();
707
					monitor.worked(10);
708
709
					File dirpath = new File(path);
710
					if (dirpath.exists()) {
711
						dirSelected = true;
712
					}
713
714
					if (dirSelected && directory.isDirectory()) {
715
716
						if (!collectProjectFilesFromDirectory(files, directory,
717
								null, monitor)) {
718
							return;
719
						}
720
						Iterator filesIterator = files.iterator();
721
						selectedProjects = new ProjectRecord[files.size()];
722
						int index = 0;
723
						monitor.worked(50);
724
						monitor
725
								.subTask(Messages.getString("ProjectMigrationWizardPage.13")); //$NON-NLS-1$
726
						while (filesIterator.hasNext()) {
727
							File file = (File) filesIterator.next();
728
							selectedProjects[index] = new ProjectRecord(file);
729
							index++;
730
						}
731
					} else {
732
						monitor.worked(60);
733
					}
734
					monitor.done();
735
				}
736
737
			});
738
		} catch (InvocationTargetException e) {
739
			IDEWorkbenchPlugin.log(e.getMessage(), e);
740
		} catch (InterruptedException e) {
741
			// Nothing to do if the user interrupts.
742
		}
743
744
		projectsList.refresh(true);
745
		projectsList.setCheckedElements(getValidProjects());
746
		if (getValidProjects().length < selectedProjects.length) {
747
			setMessage(
748
					Messages.getString("ProjectMigrationWizardPage.14"), //$NON-NLS-1$
749
					WARNING);
750
		} else {
751
			setMessage(Messages.getString("ProjectMigrationWizardPage.15")); //$NON-NLS-1$
752
		}
753
		checkForComplete();
754
	}
755
756
	/**
757
	 * Display an error dialog with the specified message.
758
	 * 
759
	 * @param message
760
	 *            the error message
761
	 */
762
	protected void displayErrorDialog(String message) {
763
		MessageDialog.openError(getContainer().getShell(),
764
				getErrorDialogTitle(), message);
765
	}
766
767
	/**
768
	 * Get the title for an error dialog. Subclasses should override.
769
	 */
770
	protected String getErrorDialogTitle() {
771
		return Messages.getString("ProjectMigrationWizardPage.16"); //$NON-NLS-1$
772
	}
773
774
	/**
775
	 * Get the title for an error dialog. Subclasses should override.
776
	 */
777
	protected String getInformationDialogTitle() {
778
		return Messages.getString("ProjectMigrationWizardPage.17"); //$NON-NLS-1$
779
	}
780
781
	/**
782
	 * Collect the list of .project files that are under directory into files.
783
	 * 
784
	 * @param files
785
	 * @param directory
786
	 * @param directoriesVisited
787
	 *            Set of canonical paths of directories, used as recursion guard
788
	 * @param monitor
789
	 *            The monitor to report to
790
	 * @return boolean <code>true</code> if the operation was completed.
791
	 */
792
	private boolean collectProjectFilesFromDirectory(Collection files,
793
			File directory, Set directoriesVisited, IProgressMonitor monitor) {
794
795
		if (monitor.isCanceled()) {
796
			return false;
797
		}
798
		monitor
799
				.subTask(NLS
800
						.bind(
801
								Messages.getString("ProjectMigrationWizardPage.18"), //$NON-NLS-1$
802
								directory.getPath()));
803
		File[] contents = directory.listFiles();
804
		if (contents == null)
805
			return false;
806
807
		// Initialize recursion guard for recursive symbolic links
808
		if (directoriesVisited == null) {
809
			directoriesVisited = new HashSet();
810
			try {
811
				directoriesVisited.add(directory.getCanonicalPath());
812
			} catch (IOException exception) {
813
				StatusManager.getManager().handle(
814
						new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH,
815
								exception.getLocalizedMessage()));
816
			}
817
		}
818
819
		// first look for project description files
820
		final String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME;
821
		for (int i = 0; i < contents.length; i++) {
822
			File file = contents[i];
823
			if (file.isFile() && file.getName().equals(dotProject)) {
824
				files.add(file);
825
				// don't search sub-directories since we can't have nested
826
				// projects
827
				return true;
828
			}
829
		}
830
		return true;
831
832
	}
833
834
	/**
835
	 * The browse button has been selected. Select the location.
836
	 */
837
	protected void handleLocationDirectoryButtonPressed() {
838
839
		DirectoryDialog dialog = new DirectoryDialog(directoryPathField
840
				.getShell());
841
		dialog
842
				.setMessage(Messages.getString("ProjectMigrationWizardPage.19")); //$NON-NLS-1$
843
844
		String dirName = directoryPathField.getText().trim();
845
		if (dirName.length() == 0) {
846
			dirName = previouslyBrowsedDirectory;
847
		}
848
849
		if (dirName.length() == 0) {
850
			dialog.setFilterPath(IDEWorkbenchPlugin.getPluginWorkspace().getRoot()
851
					.getLocation().toOSString());
852
		} else {
853
			File path = new File(dirName);
854
			if (path.exists()) {
855
				dialog.setFilterPath(new Path(dirName).toOSString());
856
			}
857
		}
858
859
		String selectedDirectory = dialog.open();
860
		if (selectedDirectory != null) {
861
			previouslyBrowsedDirectory = selectedDirectory;
862
			directoryPathField.setText(previouslyBrowsedDirectory);
863
			updateProjectsList(selectedDirectory);
864
		}
865
866
	}
867
868
	/**
869
	 * The browse button has been selected. Select the location.
870
	 */
871
	protected void handleLocationDestinationDirectoryButtonPressed() {
872
873
		DirectoryDialog dialog = new DirectoryDialog(
874
				directoryDestinationPathField.getShell());
875
		dialog
876
				.setMessage(Messages.getString("ProjectMigrationWizardPage.20")); //$NON-NLS-1$
877
878
		String dirName = directoryDestinationPathField.getText().trim();
879
		if (dirName.length() == 0) {
880
			dirName = previouslyBrowsedDestinationDirectory;
881
		}
882
883
		if (dirName.length() == 0) {
884
			dialog.setFilterPath(IDEWorkbenchPlugin.getPluginWorkspace().getRoot()
885
					.getLocation().toOSString());
886
		} else {
887
			File path = new File(dirName);
888
			if (path.exists()) {
889
				dialog.setFilterPath(new Path(dirName).toOSString());
890
			}
891
		}
892
893
		String selectedDirectory = dialog.open();
894
		if (selectedDirectory != null) {
895
			previouslyBrowsedDestinationDirectory = selectedDirectory;
896
			directoryDestinationPathField
897
					.setText(previouslyBrowsedDestinationDirectory);
898
			checkForComplete();
899
		}
900
901
	}
902
903
	/**
904
	 * Create the selected projects
905
	 * 
906
	 * @return boolean <code>true</code> if all project creations were
907
	 *         successful.
908
	 */
909
	public boolean createProjects() {
910
		//long startTime = 0;
911
		//long estimatedTime;
912
913
		saveWidgetValues();
914
		final String newProjectName = newProjectNameField.getText().trim();
915
		final String oldLinkedPath = oldLinkedPathPrefixField.getText().trim();
916
		final String newLinkedPath = newLinkedPathPrefixField.getText().trim();
917
918
		//if (showTiming)
919
			//startTime = System.nanoTime();
920
921
		final IPath sourcePath = new Path(directoryPathField.getText().trim());
922
		final IPath destinationPath = new Path(directoryDestinationPathField
923
				.getText().trim());
924
925
		WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
926
			protected void execute(IProgressMonitor monitor)
927
					throws InvocationTargetException, InterruptedException {
928
				try {
929
					ProjectMigrationOperation op = new ProjectMigrationOperation(  sourcePath,
930
							newProjectName, destinationPath,
931
							oldLinkedPath, newLinkedPath);
932
							
933
934
					monitor.beginTask("", 1); //$NON-NLS-1$
935
					if (monitor.isCanceled()) {
936
						throw new OperationCanceledException();
937
					}
938
					op.run(new SubProgressMonitor(monitor, 1));
939
					
940
					
941
				} finally {
942
					monitor.done();
943
				}
944
			}
945
		};
946
		// run the new project creation operation
947
		try {
948
			getContainer().run(true, true, op);
949
		} catch (InterruptedException e) {
950
			return false;
951
		} catch (InvocationTargetException e) {
952
			// one of the steps resulted in a core exception
953
			Throwable t = e.getTargetException();
954
			String message = Messages.getString("ProjectMigrationWizardPage.21"); //$NON-NLS-1$
955
			IStatus status;
956
			if (t instanceof CoreException) {
957
				status = ((CoreException) t).getStatus();
958
			} else {
959
				status = new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
960
						message, t);
961
			}
962
			ErrorDialog.openError(getShell(), message, null, status);
963
			return false;
964
		}
965
		return true;
966
	}
967
968
	/**
969
	 * Performs clean-up if the user cancels the wizard without doing anything
970
	 */
971
	public void performCancel() {
972
	}
973
974
	/**
975
	 * The <code>WizardDataTransfer</code> implementation of this
976
	 * <code>IOverwriteQuery</code> method asks the user whether the existing
977
	 * resource at the given path should be overwritten.
978
	 * 
979
	 * @param pathString
980
	 * @return the user's reply: one of <code>"YES"</code>, <code>"NO"</code>,
981
	 *         <code>"ALL"</code>, or <code>"CANCEL"</code>
982
	 */
983
	public String queryOverwrite(String pathString) {
984
985
		Path path = new Path(pathString);
986
987
		String messageString;
988
		// Break the message up if there is a file name and a directory
989
		// and there are at least 2 segments.
990
		if (path.getFileExtension() == null || path.segmentCount() < 2) {
991
			messageString = NLS.bind(
992
					Messages.getString("ProjectMigrationWizardPage.22"), //$NON-NLS-1$
993
					pathString);
994
		} else {
995
			messageString = NLS
996
					.bind(
997
							Messages.getString("ProjectMigrationWizardPage.23"), //$NON-NLS-1$
998
							path.lastSegment(), path.removeLastSegments(1)
999
									.toOSString());
1000
		}
1001
1002
		final MessageDialog dialog = new MessageDialog(getContainer()
1003
				.getShell(), Messages.getString("ProjectMigrationWizardPage.24"), null, //$NON-NLS-1$
1004
				messageString, MessageDialog.QUESTION, new String[] {
1005
						IDialogConstants.YES_LABEL,
1006
						IDialogConstants.YES_TO_ALL_LABEL,
1007
						IDialogConstants.NO_LABEL,
1008
						IDialogConstants.NO_TO_ALL_LABEL,
1009
						IDialogConstants.CANCEL_LABEL }, 0);
1010
		String[] response = new String[] { YES, ALL, NO, NO_ALL, CANCEL };
1011
		// run in syncExec because callback is from an operation,
1012
		// which is probably not running in the UI thread.
1013
		getControl().getDisplay().syncExec(new Runnable() {
1014
			public void run() {
1015
				dialog.open();
1016
			}
1017
		});
1018
		return dialog.getReturnCode() < 0 ? CANCEL : response[dialog
1019
				.getReturnCode()];
1020
	}
1021
1022
	/**
1023
	 * Method used for test suite.
1024
	 * 
1025
	 * @return CheckboxTreeViewer the viewer containing all the projects found
1026
	 */
1027
	public CheckboxTreeViewer getProjectsList() {
1028
		return projectsList;
1029
	}
1030
1031
	/**
1032
	 * Retrieve all the projects in the current workspace.
1033
	 * 
1034
	 * @return IProject[] array of IProject in the current workspace
1035
	 */
1036
	private IProject[] getProjectsInWorkspace() {
1037
		if (wsProjects == null) {
1038
			wsProjects = IDEWorkbenchPlugin.getPluginWorkspace().getRoot().getProjects();
1039
		}
1040
		return wsProjects;
1041
	}
1042
1043
	/**
1044
	 * Get the array of valid project records that can be imported from the
1045
	 * source workspace or archive, selected by the user. If a project with the
1046
	 * same name exists in both the source workspace and the current workspace,
1047
	 * it will not appear in the list of projects to import and thus cannot be
1048
	 * selected for import.
1049
	 * 
1050
	 * Method declared public for test suite.
1051
	 * 
1052
	 * @return ProjectRecord[] array of projects that can be imported into the
1053
	 *         workspace
1054
	 */
1055
	public ProjectRecord[] getValidProjects() {
1056
		List validProjects = new ArrayList();
1057
		for (int i = 0; i < selectedProjects.length; i++) {
1058
			if (!isProjectInWorkspace(selectedProjects[i].getProjectName())) {
1059
				validProjects.add(selectedProjects[i]);
1060
			}
1061
		}
1062
		return (ProjectRecord[]) validProjects
1063
				.toArray(new ProjectRecord[validProjects.size()]);
1064
	}
1065
1066
	/**
1067
	 * Determine if the project with the given name is in the current workspace.
1068
	 * 
1069
	 * @param projectName
1070
	 *            String the project name to check
1071
	 * @return boolean true if the project with the given name is in this
1072
	 *         workspace
1073
	 */
1074
	private boolean isProjectInWorkspace(String projectName) {
1075
		if (projectName == null) {
1076
			return false;
1077
		}
1078
		IProject[] workspaceProjects = getProjectsInWorkspace();
1079
		for (int i = 0; i < workspaceProjects.length; i++) {
1080
			if (projectName.equals(workspaceProjects[i].getName())) {
1081
				return true;
1082
			}
1083
		}
1084
		return false;
1085
	}
1086
1087
	/**
1088
	 * Use the dialog store to restore widget values to the values that they
1089
	 * held last time this wizard was used to completion.
1090
	 * 
1091
	 * Method declared public only for use of tests.
1092
	 */
1093
	public void restoreWidgetValues() {
1094
		IDialogSettings settings = getDialogSettings();
1095
		if (settings != null) {
1096
			// checkbox
1097
			/*ignoreExportedIndex = settings
1098
					.getBoolean(STORE_IGNORE_EXPORTED_INDEX_ID);
1099
			ignoreExportedIndexCheckbox.setSelection(ignoreExportedIndex);
1100
1101
			ignoreExportedProjectRefresh = settings
1102
					.getBoolean(STORE_IGNORE_EXPORTED_PROJECT_ID);
1103
			ignoreExportedProjectRefreshCheckBox
1104
					.setSelection(ignoreExportedIndex);
1105
1106
			showTiming = settings.getBoolean(STORE_SHOW_TIMING_PROJECT_ID);
1107
			showTimingCheckBox.setSelection(showTiming);
1108
			*/
1109
		}
1110
	}
1111
1112
	/**
1113
	 * Since Finish was pressed, write widget values to the dialog store so that
1114
	 * they will persist into the next invocation of this wizard page.
1115
	 * 
1116
	 * Method declared public only for use of tests.
1117
	 */
1118
	public void saveWidgetValues() {
1119
		IDialogSettings settings = getDialogSettings();
1120
		if (settings != null) {
1121
			/*settings.put(STORE_IGNORE_EXPORTED_INDEX_ID,
1122
					ignoreExportedIndexCheckbox.getSelection());
1123
1124
			settings.put(STORE_IGNORE_EXPORTED_PROJECT_ID,
1125
					ignoreExportedProjectRefreshCheckBox.getSelection());
1126
1127
			settings.put(STORE_SHOW_TIMING_PROJECT_ID, showTimingCheckBox
1128
					.getSelection());
1129
					*/
1130
		}
1131
	}
1132
1133
	/**
1134
	 * Method used for test suite.
1135
	 * 
1136
	 * @return Button copy checkbox
1137
	 */
1138
//	public Button getIgnoreExportedIndexCheckbox() {
1139
//		return ignoreExportedIndexCheckbox;
1140
//	}
1141
//
1142
	/**
1143
	 * Method used for test suite.
1144
	 * 
1145
	 * @return Button copy checkbox
1146
	 */
1147
//	public Button getIgnoreExportedProjectRefreshCheckbox() {
1148
//		return ignoreExportedProjectRefreshCheckBox;
1149
//	}
1150
	////
1151
}
(-)src/org/eclipse/ui/internal/wizards/projectmigration/messages.properties (+52 lines)
Added Link Here
1
###############################################################################
2
# Copyright (c) 2000, 2006 IBM Corporation and others.
3
# All rights reserved. This program and the accompanying materials
4
# are made available under the terms of the Eclipse Public License v1.0
5
# which accompanies this distribution, and is available at
6
# http://www.eclipse.org/legal/epl-v10.html
7
#
8
# Contributors:
9
#     IBM Corporation - initial API and implementation
10
11
###############################################################################
12
13
ProjectMigrationExportWizard.0=Export
14
ProjectMigrationExportWizardPage.1=Export Project Migration Information for use in a project migration
15
ProjectMigrationExportWizardPage.2=Select &projects to export:
16
ProjectMigrationExportWizardPage.3=&Select All
17
ProjectMigrationExportWizardPage.4=&Deselect All
18
ProjectMigrationExportWizardPage.5=Errors occurred while exporting project migration information
19
ProjectMigrationExportWizardPage.7=At least one project must be selected.
20
ProjectMigrationExportWizardPage.8=Export Project Migration Information
21
22
ProjectMigrationExportWizardPage.0=Export Project Migration Information
23
ProjectMigrationExportWizardPage.6=Errors occurred while exporting project migration information
24
ProjectMigrationOperation.0=Creating Projects
25
ProjectMigrationOperation.1=Migration Interrupted
26
ProjectMigrationWizard_0=Migrate
27
ProjectMigrationWizard.0=Migrate
28
ProjectMigrationWizardPage.0={0} ({1})
29
ProjectMigrationWizardPage.1=Project Migration
30
ProjectMigrationWizardPage.10=B&rowse...
31
ProjectMigrationWizardPage.11=Select a directory to search for existing Eclipse projects
32
ProjectMigrationWizardPage.12=Searching for projects
33
ProjectMigrationWizardPage.13=Processing results
34
ProjectMigrationWizardPage.14=Some projects were hidden because they exist in the workspace directory
35
ProjectMigrationWizardPage.15=Select a directory to search for existing Eclipse projects
36
ProjectMigrationWizardPage.16=Internal error
37
ProjectMigrationWizardPage.17=Project Migration Error
38
ProjectMigrationWizardPage.18=Checking: {0}
39
ProjectMigrationWizardPage.19=Select source directory of the project to migrate
40
ProjectMigrationWizardPage.2=Select a directory to search for existing Eclipse project.
41
ProjectMigrationWizardPage.20=Select destination directory of the migrated project
42
ProjectMigrationWizardPage.21=Creation Problems
43
ProjectMigrationWizardPage.22=''{0}'' already exists. Would you like to overwrite it?
44
ProjectMigrationWizardPage.23=Overwrite ''{0}'' in folder ''{1}''?
45
ProjectMigrationWizardPage.24=Question
46
ProjectMigrationWizardPage.3=&Project:
47
ProjectMigrationWizardPage.4=Old Linked Path Prefix:
48
ProjectMigrationWizardPage.5=New Linked Path Prefix:
49
ProjectMigrationWizardPage.6=&Destination Directory:
50
ProjectMigrationWizardPage.7=B&rowse...
51
ProjectMigrationWizardPage.8=&Destination Project Name:
52
ProjectMigrationWizardPage.9=Select &source directory:

Return to bug 263671