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 (+480 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(String projName, IPath sourcePath, String newName, IPath destinationPath){
90
		super();
91
		this.projectName = projName;
92
		this.sourcePath = sourcePath;
93
		this.destinationPath = destinationPath;
94
		this.newProjectName = newName;
95
		this.oldLinkedPathPrefix = ""; //$NON-NLS-1$
96
		this.newLinkedPathPrefix = ""; //$NON-NLS-1$
97
	}
98
99
	/**
100
	 * Sets the linked directory path prefix.
101
	 * 
102
	 * @param oldLinkedPathPrefix
103
	 *            linked to the old directory path prefix
104
	 * @param newLinkedPathPrefix
105
	 *            linked to the new directory path prefix
106
	 */
107
	public void setLinkedPathPrefix(String oldLinkedPathPrefix, String newLinkedPathPrefix) {
108
		this.oldLinkedPathPrefix = oldLinkedPathPrefix;
109
		this.newLinkedPathPrefix = newLinkedPathPrefix;
110
	}
111
112
113
	/*
114
	 * Method declared on WorkbenchModifyOperation. Imports the specified
115
	 * project from the file system.
116
	 * 
117
	 * @param progressMonitor IProgressMonitor object
118
	 */
119
	public void execute(IProgressMonitor progressMonitor) throws Exception {
120
		/* TODO: remove this?
121
		 * Check the cdt debug activity settings. If on, print a message to
122
		 * stdout announcing that the Project migration is starting. This makes
123
		 * timing the migration easier. Please note that the hard-coded
124
		 * references to the plugin and activity names is a bit of a kludge. It
125
		 * would not be needed if the project migration API were actually part
126
		 * of CDT instead of in a separate plugin.
127
		 */
128
		String option = "org.eclipse.cdt.core/debug/indexer/activity"; //$NON-NLS-1$
129
		String trace = Platform.getDebugOption(option);
130
		boolean internallyActivated = Boolean.getBoolean(option);
131
		boolean showActivity = internallyActivated || (trace != null && trace.equalsIgnoreCase("true")); //$NON-NLS-1$
132
		if (showActivity == true) {
133
			System.out.println(Messages.getString("ProjectMigration.0")); //$NON-NLS-1$
134
		}
135
		IProgressMonitor monitor = progressMonitor;
136
		if( monitor == null ) {
137
			monitor = new NullProgressMonitor();
138
		}
139
		monitor.beginTask("", 100 ); //$NON-NLS-1$
140
		if (sourcePath.equals(destinationPath)) {
141
			throw new Exception(Messages.getString("ProjectMigration.1")); //$NON-NLS-1$
142
		}
143
		try {
144
			extractMigrationFiles(sourcePath, destinationPath);
145
			
146
			File[] projectFiles = getProjectFiles(sourcePath);
147
			if (projectFiles.length == 0) {
148
				throw new Exception(Messages.getString("ProjectMigration.2")); //$NON-NLS-1$
149
			}
150
			int i = 0;
151
152
			for (i = 0; i < projectFiles.length; i++) {
153
				File file = projectFiles[i];
154
				if (file != null) {
155
					if (!copyRecursively(file, destinationPath, new SubProgressMonitor( monitor, 20/projectFiles.length))) {
156
						throw new Exception(Messages.getString("ProjectMigration.4")); //$NON-NLS-1$
157
					}
158
				}
159
			}
160
161
			IPath path = destinationPath;
162
			
163
			/*
164
			 * Let the project migration helpers have a chance at changing the copied files.
165
			 */
166
			changeCopiedFiles( projectFiles, new SubProgressMonitor( monitor, 20 ) );
167
			
168
//	PlatformProjectMigrationHelper projFile = new PlatformProjectMigrationHelper(path, projectFiles, newProjectName, oldLinkedPathPrefix, newLinkedPathPrefix);
169
	
170
//			projFile.performProjectRenaming(new SubProgressMonitor(monitor,20));
171
	
172
			path = destinationPath.append(IProjectDescription.DESCRIPTION_FILE_NAME);
173
	
174
			final IWorkspace workspace = ResourcesPlugin.getWorkspace();
175
			IProjectDescription description = workspace.loadProjectDescription(path);
176
			String projName = description.getName();
177
			final IProject project = workspace.getRoot().getProject(projName);
178
	
179
			File importFile = destinationPath.append(ProjectMigration.SNAP_NAME).toFile();
180
			if (importFile.exists()) {
181
				SFSUtilities.startUsingRefreshInfo(description, destinationPath, ProjectMigration.SNAP_NAME, projectFiles.length);
182
				for(  i = 0; i < projectFiles.length; i++ ) {
183
					SFSUtilities.addRootLocalFile(projectFiles[i].getName()); 
184
				}
185
			}
186
	
187
			project.create(description, new SubProgressMonitor( monitor, 10 ));
188
	
189
			// open the project and perform the refresh before returning
190
			project.open(IResource.NONE, new SubProgressMonitor( monitor, 40 ) );
191
		}
192
		finally {
193
			// now turn off the use of the snapshot file, if active
194
			SFSUtilities.stopUsingRefreshInfo();
195
		}
196
		monitor.done();
197
	}
198
	
199
	private void changeCopiedFiles(File[] projectFiles, IProgressMonitor monitor) {
200
		IExecutableExtension[] extensions = getMigrationHelpers();
201
		if( extensions.length == 0 ) {
202
			monitor.done();
203
			return;
204
		}			
205
		for( int i = 0; i < projectFiles.length; i++ ) {
206
207
			/*
208
			 * Ask the helpers to migrate files that are copied.
209
			 */
210
211
			for( int j = 0; j < extensions.length; j ++ ) {
212
				if (extensions[j] instanceof ProjectMigrationHelper) {
213
					ProjectMigrationHelper helper = (ProjectMigrationHelper) extensions[j];
214
					IPath filePath = destinationPath.append( projectFiles[i].getName());
215
					helper.migrateFile( filePath, projectName, newProjectName, oldLinkedPathPrefix, newLinkedPathPrefix);
216
				}
217
			}
218
			monitor.worked(1);
219
		}
220
	}
221
222
	/*
223
	 * Get the set of migration helpers. We don't match on the natures since no
224
	 * projects are actually open. Instead, the migration helper must "know" which
225
	 * files it can help migrate.
226
	 */
227
	private IExecutableExtension[] getMigrationHelpers() {
228
		List helpers = new ArrayList();
229
230
		try {
231
	        IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_MIGRATION_HELPERS);
232
			if (extension != null) {
233
				IExtension[] extensions = extension.getExtensions();
234
				for (int i = 0; i < extensions.length; i++ ) {
235
					IExtension extension2 = extensions[i]; 
236
					IConfigurationElement[] configElements = extension2.getConfigurationElements();
237
					for ( int j = 0; j < configElements.length; j ++ ) {
238
						IConfigurationElement configElement = configElements[j];
239
						if( configElement.getAttribute( "class" ) != null ) { //$NON-NLS-1$
240
							helpers.add( configElement.createExecutableExtension("class")); //$NON-NLS-1$
241
						}
242
					}
243
				}
244
			}
245
		} catch (CoreException e) {
246
			ResourcesPlugin.getPlugin().getLog().log(new Status( IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, Messages.getString("ExportProjectMigrationInfo.4"), e));  //$NON-NLS-1$
247
		}
248
		
249
		return (IExecutableExtension[]) helpers.toArray(new IExecutableExtension[0]);
250
			
251
	}
252
	
253
		private void readEntry(ZipFile zip, ZipEntry entry, File tmpFile)
254
				throws IOException {
255
			InputStream stream = zip.getInputStream(entry);
256
			OutputStream outEntry = new FileOutputStream(tmpFile);
257
			try {
258
				byte[] buffer = new byte[2048];
259
				int read;
260
				while ((read = stream.read(buffer)) >= 0) {
261
					outEntry.write(buffer, 0, read);
262
				}
263
			} finally {
264
				close(outEntry);
265
			}
266
		}
267
268
		private void close(OutputStream out) {
269
			try {
270
				if (out != null) {
271
					out.close();
272
				}
273
			} catch (IOException e) {
274
				ResourcesPlugin.getPlugin().getLog().log( new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ExportProjectMigrationInfo.2"), e)); //$NON-NLS-1$
275
276
			}
277
		}
278
279
280
281
	/**
282
	 * Copies the specified file system object recursively into the destination
283
	 * If the import fails, adds a status object to the list to be returned by
284
	 * <code>getStatus</code>.
285
	 * 
286
	 * @param file
287
	 *            the file system object to be imported
288
	 * @exception OperationCanceledException
289
	 *                if canceled
290
	 */
291
	private boolean copyRecursively(File file, IPath destPath, IProgressMonitor monitor) {
292
		if (monitor.isCanceled()) {
293
			throw new OperationCanceledException();
294
		}
295
		if (!file.isDirectory()) {
296
			return copyFile(file, destPath, monitor);
297
		}
298
299
		IPath folderPath = destPath.addTrailingSeparator();
300
		folderPath = folderPath.append(file.getName());
301
		boolean success = new File(folderPath.toOSString()).mkdir();
302
		if (!success) {
303
			monitor.done();
304
			return false;
305
		}
306
		File[] contents = file.listFiles();
307
		monitor.beginTask("", contents.length); //$NON-NLS-1$
308
		for (int i = 0; i < contents.length; i++) {
309
			if (!copyRecursively(contents[i], folderPath, new SubProgressMonitor( monitor, 1 ) )) {
310
				monitor.done();
311
				return false;
312
			}
313
		}
314
		monitor.done();
315
		return true;
316
	}
317
318
	/**
319
	 * Copies the specified file system object into the destination. If the copy
320
	 * fails, returns false.
321
	 */
322
	private boolean copyFile(File file, IPath dPath, IProgressMonitor monitor) {
323
324
		String filePath = file.getAbsolutePath();
325
		monitor.subTask(filePath);
326
327
		// assume that the source and target are not the same
328
		try {
329
			FileInputStream from = null;
330
			try {
331
				from = new FileInputStream(file);
332
			} catch (FileNotFoundException e) {
333
				// file was not found. null case is handled.
334
			}
335
			if (from == null) {
336
				monitor.done();
337
				return false;
338
			}
339
			IPath destPath = dPath.addTrailingSeparator();
340
			destPath = destPath.append(file.getName());
341
			FileOutputStream to = null;
342
			try {
343
				to = new FileOutputStream(destPath.toString());
344
			} catch (FileNotFoundException e) {
345
				from.close();
346
				monitor.done();
347
				return false;
348
			}
349
			try {
350
				byte[] buffer = new byte[4096];
351
				int bytesRead;
352
353
				while ((bytesRead = from.read(buffer)) != -1)
354
					to.write(buffer, 0, bytesRead); // write
355
			} finally {
356
				try {
357
					from.close();
358
				} catch (IOException e) {
359
					ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.6"), e)); //$NON-NLS-1$
360
361
				}
362
363
				try {
364
					to.close();
365
				} catch (IOException e) {
366
					ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.7"), e)); //$NON-NLS-1$
367
368
				}
369
			}
370
			monitor.done();
371
			return true;
372
		} catch (IOException e) {
373
			monitor.done();
374
			return false;
375
		}
376
	}
377
378
	/**
379
	 * Get the list of files that need to be copied from this directory. This
380
	 * includes .project, and any 0-length entries in the zip file. The 0-length
381
	 * entries are used to capture the names of files that the migration helper
382
	 * extensions wanted to have copied.
383
	 */
384
	private File[] getProjectFiles(IPath importSourcePath) {
385
		List files = new ArrayList();
386
		File[] contents = importSourcePath.toFile().listFiles();
387
		if (contents == null) {
388
			return null;
389
		}
390
391
		/*
392
		 * Look for the Migration zip file
393
		 */
394
		int migZipIndex = -1;
395
		for (int i = 1; i < contents.length; i++) {
396
			File file = contents[i];
397
			if ((!file.isDirectory() && file.getName().equals(ProjectMigration.MIGRATION_ZIP_NAME))) {
398
				migZipIndex = i;
399
			}
400
		}
401
		if (migZipIndex == -1) {
402
			return new File[0];
403
		}
404
		files.add(contents[migZipIndex]);
405
406
		/*
407
		 * Open the zip file and get the list of names for the entries that are 0 length. This
408
		 * should be a list of files to copy. Verify that the names are in the contents.
409
		 */
410
411
		try {
412
			ZipFile zip = new ZipFile(contents[migZipIndex]);
413
			Enumeration zipEntriesList = zip.entries();
414
			try {
415
				while (true) {
416
					ZipEntry entry;
417
					entry = (ZipEntry) zipEntriesList.nextElement();
418
					if (entry.getSize() == 0) {
419
						File entryFile = importSourcePath.append(entry.getName()).toFile();
420
						if( entryFile.exists() ) {
421
							files.add( entryFile );
422
						}
423
					}
424
				}
425
			} catch (NoSuchElementException e) {
426
				// done with all entries
427
			} finally {
428
				zip.close();
429
			}
430
		} catch (ZipException e) {
431
			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.8"), e)); //$NON-NLS-1$
432
		} catch (IOException e) {
433
			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.9"), e)); //$NON-NLS-1$
434
435
		}
436
437
		return (File[]) files.toArray(new File[0]);
438
	}
439
	/**
440
	 * Extract non-zero length files form the zip file into the destination directory.
441
	 */
442
	private void extractMigrationFiles(IPath importSourcePath, IPath dPath) {
443
		
444
		/*
445
		 * Look for the Migration zip file
446
		 */
447
		File zipFile = importSourcePath.append(ProjectMigration.MIGRATION_ZIP_NAME).toFile();
448
		if( !zipFile.exists() ) {
449
			return;
450
		}
451
		
452
		try {
453
			ZipFile zip = new ZipFile(zipFile);
454
			Enumeration zipEntriesList = zip.entries();
455
			try {
456
				while (true) {
457
					ZipEntry entry;
458
					entry = (ZipEntry) zipEntriesList.nextElement();
459
					if (entry.getSize() != 0 && entry.getName().equals(ProjectMigration.MIGRATION_ZIP_NAME)) {
460
						File tmpFile = dPath.append(entry.getName()).toFile();
461
						readEntry( zip, entry, tmpFile);
462
					}
463
				}
464
			} catch (NoSuchElementException e) {
465
				// done with all entries
466
			} finally {
467
				zip.close();
468
			}
469
		} catch (ZipException e) {
470
			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.8"), e)); //$NON-NLS-1$
471
		} catch (IOException e) {
472
			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, Messages.getString("ProjectMigration.9"), e)); //$NON-NLS-1$
473
474
		}
475
476
		return ;
477
	}
478
479
480
}
(-)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 (+190 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.internal.resources.projectmigration.SnapInfo;
14
15
import java.io.File;
16
import java.io.RandomAccessFile;
17
import java.io.IOException;
18
19
import org.eclipse.core.filesystem.EFS;
20
import org.eclipse.core.filesystem.IFileInfo;
21
import org.eclipse.core.filesystem.IFileStore;
22
import org.eclipse.core.runtime.IPath;
23
import org.eclipse.core.runtime.Path;
24
import org.eclipse.core.runtime.IProgressMonitor;
25
import org.eclipse.core.runtime.CoreException;
26
27
/**
28
 * This class writes and reads a file which represent a snapshot of a particular
29
 * directory and all of its contained files
30
 */
31
32
public class SnapInfoStore {
33
	String rootPath; // the root directory for the snapshot
34
	File storeFile; // the file to write to or read from
35
	int fileCount; // total number of files in the store
36
	int rootLocals; // number of spaces reserved for local
37
38
	// pass-through files in the root directory
39
40
	public SnapInfoStore(String rootPath, File storeFile, int rootLocals) {
41
		this.rootPath = rootPath;
42
		this.storeFile = storeFile;
43
		this.rootLocals = rootLocals;
44
	}
45
46
	public SnapInfoStore(String rootPath, File storeFile) {
47
		this.rootPath = rootPath;
48
		this.storeFile = storeFile;
49
		this.rootLocals = 0;
50
	}
51
52
	public boolean write(IProgressMonitor monitor) {
53
		boolean ret = false;
54
		if (!rootPath.equals("")) { //$NON-NLS-1$
55
			IFileStore rootStore = EFS.getLocalFileSystem().getStore(
56
					new Path(rootPath));
57
			IFileInfo info = rootStore.fetchInfo();
58
			if (info != null && info.exists()) {
59
				try {
60
					storeFile.delete();
61
					fileCount = 1;
62
					RandomAccessFile out = new RandomAccessFile(storeFile, "rw"); //$NON-NLS-1$
63
					out.writeInt(0); // will be rewritten with total file count
64
					// write dummy record for root directory
65
					out.writeInt(SnapInfo.ATTRIBUTE_DIRECTORY);
66
					out.writeLong(0);
67
					out.writeLong(0);
68
					IPath path = new Path(rootPath);
69
					String name = path.lastSegment();
70
					out.writeUTF(name != null ? name : ""); //$NON-NLS-1$
71
					ret = writeChildren(monitor, out, rootStore);
72
					out.seek(0);
73
					out.writeInt(fileCount);
74
					out.close();
75
				} catch (IOException e) {
76
					return false;
77
				}
78
			}
79
		}
80
		return ret;
81
	}
82
83
	public SnapInfo[] read(IProgressMonitor monitor) {
84
		try {
85
			if (storeFile.exists()) {
86
				RandomAccessFile in = new RandomAccessFile(storeFile, "r"); //$NON-NLS-1$
87
				int totalCount = in.readInt();
88
				if (totalCount != 0) {
89
					SnapInfo[] infos = new SnapInfo[totalCount + rootLocals];
90
					fileCount = 0;
91
					SnapInfo snap = readInfo(in); // read root entry
92
					infos[0] = snap;
93
					fileCount = rootLocals + 1; // reserve for root locals
94
					snap = readChildren(in, 0, infos);
95
					snap.setNextIndex(0); // end of root dir entries
96
					return infos;
97
				}
98
			}
99
		} catch (IOException e) {
100
			return null;
101
		}
102
		return null;
103
	}
104
105
	private boolean writeChildren(IProgressMonitor monitor,
106
			RandomAccessFile out, IFileStore parent) {
107
		try {
108
			String[] children = parent.childNames(EFS.NONE, monitor);
109
			out.writeInt(children.length);
110
			for (int i = 0; i < children.length; i++) {
111
				IFileStore store = parent.getChild(children[i]);
112
				// possible speedup if following line calls fetchInfo()?
113
				IFileInfo info = store.fetchInfo(EFS.NONE, monitor);
114
				if (!writeInfo(out, info))
115
					return false;
116
				if (info.isDirectory() && !writeChildren(monitor, out, store))
117
					return false;
118
			}
119
			return true;
120
		} catch (CoreException e) {
121
			return false;
122
		} catch (IOException e) {
123
			return false;
124
		}
125
	}
126
127
	private boolean writeInfo(RandomAccessFile out, IFileInfo info) {
128
		try {
129
			int attributes = 0;
130
			if (info.getAttribute(EFS.ATTRIBUTE_ARCHIVE))
131
				attributes |= EFS.ATTRIBUTE_ARCHIVE;
132
			if (info.getAttribute(EFS.ATTRIBUTE_EXECUTABLE))
133
				attributes |= EFS.ATTRIBUTE_EXECUTABLE;
134
			if (info.getAttribute(EFS.ATTRIBUTE_HIDDEN))
135
				attributes |= EFS.ATTRIBUTE_HIDDEN;
136
			// if (info.getAttribute(EFS.ATTRIBUTE_SYMLINK))
137
			// attributes |= EFS.ATTRIBUTE_SYMLINK;
138
			if (info.getAttribute(EFS.ATTRIBUTE_READ_ONLY))
139
				attributes |= EFS.ATTRIBUTE_READ_ONLY;
140
			if (info.isDirectory())
141
				attributes |= SnapInfo.ATTRIBUTE_DIRECTORY;
142
			out.writeInt(attributes);
143
			// if ((attributes & EFS.ATTRIBUTE_SYMLINK) != 0) {
144
			// String link = info.getStringAttribute(EFS.ATTRIBUTE_LINK_TARGET);
145
			// out.writeUTF(link);
146
			// }
147
			out.writeLong(info.getLastModified());
148
			out.writeLong(info.getLength());
149
			out.writeUTF(info.getName());
150
			++fileCount;
151
			return true;
152
		} catch (IOException e) {
153
			return false;
154
		}
155
	}
156
157
	private SnapInfo readChildren(RandomAccessFile in, int parentIndex,
158
			SnapInfo[] infos) throws IOException {
159
		SnapInfo snap = null;
160
		int nChildren = in.readInt();
161
		for (int i = 0; i < nChildren; i++) {
162
			snap = readInfo(in);
163
			infos[fileCount++] = snap;
164
			if (snap.isDirectory()) {
165
				snap.setChildIndex(fileCount); // assume non-empty
166
				SnapInfo last = readChildren(in, fileCount - 1, infos);
167
				if (last != null)
168
					last.setNextIndex(0); // end of this directory
169
				else
170
					snap.setChildIndex(0); // directory was empty
171
			}
172
			snap.setNextIndex(fileCount);
173
			snap.setParentIndex(parentIndex);
174
		}
175
		return snap;
176
	}
177
178
	private SnapInfo readInfo(RandomAccessFile in) throws IOException {
179
		int attributes = in.readInt();
180
		long lastModified = in.readLong();
181
		long length = in.readLong();
182
		String name = in.readUTF();
183
		SnapInfo snap = new SnapInfo(name);
184
		snap.setAttributes(attributes);
185
		snap.setLastModified(lastModified);
186
		snap.setLength(length);
187
		return snap;
188
	}
189
190
}
(-)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 (+108 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
	private String projectName;
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 projName name of project being migrated
60
	 * 
61
	 * @param destinationPath
62
	 *            full path of destination directory
63
	 * @param sourcePath
64
	 *            file system object for project to import
65
	 * @param newProjName 
66
	 * @param oldLinkedPathPrefix 
67
	 * @param newLinkedPathPrefix 
68
	 */
69
	public ProjectMigrationOperation(String projName, IPath sourcePath, 
70
			String newProjName, IPath destinationPath, 
71
			String oldLinkedPathPrefix,	String newLinkedPathPrefix ) {
72
		super();
73
		this.sourcePath = sourcePath;
74
		this.destinationPath = destinationPath;
75
		this.projectName = projName;
76
		this.newProjectName = newProjName;
77
		this.oldLinkedPathPrefix = oldLinkedPathPrefix;
78
		this.newLinkedPathPrefix = newLinkedPathPrefix;
79
		//this.ignoreIndex = ignoreIndex;
80
		//this.ignoreFileInfo = ignoreFileInfo;
81
	}
82
83
	/*
84
	 * (non-Javadoc) Method declared on WorkbenchModifyOperation. Imports the
85
	 * specified project from the file system.
86
	 */
87
	protected void execute(IProgressMonitor monitor) throws CoreException {
88
		ProjectMigration pm = new ProjectMigration(projectName, sourcePath, newProjectName, destinationPath);
89
90
		pm.setLinkedPathPrefix(oldLinkedPathPrefix, newLinkedPathPrefix);
91
		//pm.setIgnoreIndex(ignoreIndex);
92
		//pm.setIgnoreFileInfo(ignoreFileInfo);
93
94
		try {
95
			monitor
96
					.beginTask(
97
							Messages.getString("ProjectMigrationOperation.0"), //$NON-NLS-1$
98
							100);
99
			pm.execute(monitor);
100
		} catch (Exception e) {
101
			throw new CoreException(new Status(IStatus.ERROR,
102
					IDEWorkbenchPlugin.IDE_WORKBENCH, 0, Messages.getString("ProjectMigrationOperation.1"), e)); //$NON-NLS-1$
103
		} finally {
104
			monitor.done();
105
		}
106
	}
107
108
}
(-)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 (+1153 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
		final String projectName = ((ProjectRecord)(getProjectsList().getCheckedElements()[0])).getProjectName();
918
919
920
		//if (showTiming)
921
			//startTime = System.nanoTime();
922
923
		final IPath sourcePath = new Path(directoryPathField.getText().trim());
924
		final IPath destinationPath = new Path(directoryDestinationPathField
925
				.getText().trim());
926
927
		WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
928
			protected void execute(IProgressMonitor monitor)
929
					throws InvocationTargetException, InterruptedException {
930
				try {
931
					ProjectMigrationOperation op = new ProjectMigrationOperation( projectName, sourcePath,
932
							newProjectName, destinationPath,
933
							oldLinkedPath, newLinkedPath);
934
							
935
936
					monitor.beginTask("", 1); //$NON-NLS-1$
937
					if (monitor.isCanceled()) {
938
						throw new OperationCanceledException();
939
					}
940
					op.run(new SubProgressMonitor(monitor, 1));
941
					
942
					
943
				} finally {
944
					monitor.done();
945
				}
946
			}
947
		};
948
		// run the new project creation operation
949
		try {
950
			getContainer().run(true, true, op);
951
		} catch (InterruptedException e) {
952
			return false;
953
		} catch (InvocationTargetException e) {
954
			// one of the steps resulted in a core exception
955
			Throwable t = e.getTargetException();
956
			String message = Messages.getString("ProjectMigrationWizardPage.21"); //$NON-NLS-1$
957
			IStatus status;
958
			if (t instanceof CoreException) {
959
				status = ((CoreException) t).getStatus();
960
			} else {
961
				status = new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
962
						message, t);
963
			}
964
			ErrorDialog.openError(getShell(), message, null, status);
965
			return false;
966
		}
967
		return true;
968
	}
969
970
	/**
971
	 * Performs clean-up if the user cancels the wizard without doing anything
972
	 */
973
	public void performCancel() {
974
	}
975
976
	/**
977
	 * The <code>WizardDataTransfer</code> implementation of this
978
	 * <code>IOverwriteQuery</code> method asks the user whether the existing
979
	 * resource at the given path should be overwritten.
980
	 * 
981
	 * @param pathString
982
	 * @return the user's reply: one of <code>"YES"</code>, <code>"NO"</code>,
983
	 *         <code>"ALL"</code>, or <code>"CANCEL"</code>
984
	 */
985
	public String queryOverwrite(String pathString) {
986
987
		Path path = new Path(pathString);
988
989
		String messageString;
990
		// Break the message up if there is a file name and a directory
991
		// and there are at least 2 segments.
992
		if (path.getFileExtension() == null || path.segmentCount() < 2) {
993
			messageString = NLS.bind(
994
					Messages.getString("ProjectMigrationWizardPage.22"), //$NON-NLS-1$
995
					pathString);
996
		} else {
997
			messageString = NLS
998
					.bind(
999
							Messages.getString("ProjectMigrationWizardPage.23"), //$NON-NLS-1$
1000
							path.lastSegment(), path.removeLastSegments(1)
1001
									.toOSString());
1002
		}
1003
1004
		final MessageDialog dialog = new MessageDialog(getContainer()
1005
				.getShell(), Messages.getString("ProjectMigrationWizardPage.24"), null, //$NON-NLS-1$
1006
				messageString, MessageDialog.QUESTION, new String[] {
1007
						IDialogConstants.YES_LABEL,
1008
						IDialogConstants.YES_TO_ALL_LABEL,
1009
						IDialogConstants.NO_LABEL,
1010
						IDialogConstants.NO_TO_ALL_LABEL,
1011
						IDialogConstants.CANCEL_LABEL }, 0);
1012
		String[] response = new String[] { YES, ALL, NO, NO_ALL, CANCEL };
1013
		// run in syncExec because callback is from an operation,
1014
		// which is probably not running in the UI thread.
1015
		getControl().getDisplay().syncExec(new Runnable() {
1016
			public void run() {
1017
				dialog.open();
1018
			}
1019
		});
1020
		return dialog.getReturnCode() < 0 ? CANCEL : response[dialog
1021
				.getReturnCode()];
1022
	}
1023
1024
	/**
1025
	 * Method used for test suite.
1026
	 * 
1027
	 * @return CheckboxTreeViewer the viewer containing all the projects found
1028
	 */
1029
	public CheckboxTreeViewer getProjectsList() {
1030
		return projectsList;
1031
	}
1032
1033
	/**
1034
	 * Retrieve all the projects in the current workspace.
1035
	 * 
1036
	 * @return IProject[] array of IProject in the current workspace
1037
	 */
1038
	private IProject[] getProjectsInWorkspace() {
1039
		if (wsProjects == null) {
1040
			wsProjects = IDEWorkbenchPlugin.getPluginWorkspace().getRoot().getProjects();
1041
		}
1042
		return wsProjects;
1043
	}
1044
1045
	/**
1046
	 * Get the array of valid project records that can be imported from the
1047
	 * source workspace or archive, selected by the user. If a project with the
1048
	 * same name exists in both the source workspace and the current workspace,
1049
	 * it will not appear in the list of projects to import and thus cannot be
1050
	 * selected for import.
1051
	 * 
1052
	 * Method declared public for test suite.
1053
	 * 
1054
	 * @return ProjectRecord[] array of projects that can be imported into the
1055
	 *         workspace
1056
	 */
1057
	public ProjectRecord[] getValidProjects() {
1058
		List validProjects = new ArrayList();
1059
		for (int i = 0; i < selectedProjects.length; i++) {
1060
			if (!isProjectInWorkspace(selectedProjects[i].getProjectName())) {
1061
				validProjects.add(selectedProjects[i]);
1062
			}
1063
		}
1064
		return (ProjectRecord[]) validProjects
1065
				.toArray(new ProjectRecord[validProjects.size()]);
1066
	}
1067
1068
	/**
1069
	 * Determine if the project with the given name is in the current workspace.
1070
	 * 
1071
	 * @param projectName
1072
	 *            String the project name to check
1073
	 * @return boolean true if the project with the given name is in this
1074
	 *         workspace
1075
	 */
1076
	private boolean isProjectInWorkspace(String projectName) {
1077
		if (projectName == null) {
1078
			return false;
1079
		}
1080
		IProject[] workspaceProjects = getProjectsInWorkspace();
1081
		for (int i = 0; i < workspaceProjects.length; i++) {
1082
			if (projectName.equals(workspaceProjects[i].getName())) {
1083
				return true;
1084
			}
1085
		}
1086
		return false;
1087
	}
1088
1089
	/**
1090
	 * Use the dialog store to restore widget values to the values that they
1091
	 * held last time this wizard was used to completion.
1092
	 * 
1093
	 * Method declared public only for use of tests.
1094
	 */
1095
	public void restoreWidgetValues() {
1096
		IDialogSettings settings = getDialogSettings();
1097
		if (settings != null) {
1098
			// checkbox
1099
			/*ignoreExportedIndex = settings
1100
					.getBoolean(STORE_IGNORE_EXPORTED_INDEX_ID);
1101
			ignoreExportedIndexCheckbox.setSelection(ignoreExportedIndex);
1102
1103
			ignoreExportedProjectRefresh = settings
1104
					.getBoolean(STORE_IGNORE_EXPORTED_PROJECT_ID);
1105
			ignoreExportedProjectRefreshCheckBox
1106
					.setSelection(ignoreExportedIndex);
1107
1108
			showTiming = settings.getBoolean(STORE_SHOW_TIMING_PROJECT_ID);
1109
			showTimingCheckBox.setSelection(showTiming);
1110
			*/
1111
		}
1112
	}
1113
1114
	/**
1115
	 * Since Finish was pressed, write widget values to the dialog store so that
1116
	 * they will persist into the next invocation of this wizard page.
1117
	 * 
1118
	 * Method declared public only for use of tests.
1119
	 */
1120
	public void saveWidgetValues() {
1121
		IDialogSettings settings = getDialogSettings();
1122
		if (settings != null) {
1123
			/*settings.put(STORE_IGNORE_EXPORTED_INDEX_ID,
1124
					ignoreExportedIndexCheckbox.getSelection());
1125
1126
			settings.put(STORE_IGNORE_EXPORTED_PROJECT_ID,
1127
					ignoreExportedProjectRefreshCheckBox.getSelection());
1128
1129
			settings.put(STORE_SHOW_TIMING_PROJECT_ID, showTimingCheckBox
1130
					.getSelection());
1131
					*/
1132
		}
1133
	}
1134
1135
	/**
1136
	 * Method used for test suite.
1137
	 * 
1138
	 * @return Button copy checkbox
1139
	 */
1140
//	public Button getIgnoreExportedIndexCheckbox() {
1141
//		return ignoreExportedIndexCheckbox;
1142
//	}
1143
//
1144
	/**
1145
	 * Method used for test suite.
1146
	 * 
1147
	 * @return Button copy checkbox
1148
	 */
1149
//	public Button getIgnoreExportedProjectRefreshCheckbox() {
1150
//		return ignoreExportedProjectRefreshCheckBox;
1151
//	}
1152
	////
1153
}
(-)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