Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 2ca19589a0341af13d27fe4410b7574c69050b36 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Dan Rubel - project set serializer API
 *******************************************************************************/
package org.eclipse.team.core;

import java.io.File;
import java.util.*;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.team.internal.core.Policy;

/**
 * An object for serializing and deserializing
 * references to projects.  Given a project, it can produce a
 * UTF-8 encoded String which can be stored in a file.
 * Given this String, it can load a project into the workspace.
 * It also provides a mechanism
 * by which repository providers can be notified when a project set is created and exported.
 * 
 * @see RepositoryProviderType
 * 
 * @since 2.1
 */
public abstract class ProjectSetCapability {
	
	/**
	 * Ensure that the provider type is backwards compatible by
	 * passing the project set serializer to the type if a serializer
	 * is registered. This is required for repository providers
	 * who implemented a project set capability in 2.1 (before the
	 * capability contained the serialization API) and have not
	 * released a 3.0 plugin yet. This method is
	 * called before project set export and import and can be used by
	 * other clients who work with project sets.
	 * 
	 * @param type the provider type instance
	 * @param capability the capability that was obtained from the provider type
	 * 
	 * @since 3.0
	 */
	public static void ensureBackwardsCompatible(RepositoryProviderType type, ProjectSetCapability capability) {
		if (capability != null) {
			IProjectSetSerializer oldSerializer = Team.getProjectSetSerializer(type.getID());
			if (oldSerializer != null) {
				capability.setSerializer(oldSerializer);
			}
		}
	}
	
	/**
	 * The old serialization interface
	 */
	private IProjectSetSerializer serializer;
	
	/**
	 * Notify the provider that a project set has been created at path. Only
	 * providers identified as having projects in the project set will be
	 * notified. The project set may or may not be created in a workspace
	 * project (thus may not be a resource).
	 * 
	 * @param file the project set file that was created
	 * @param context a UI context object. This object will either be a 
	 *                 com.ibm.swt.widgets.Shell or it will be null.
	 * @param monitor a progress monitor
	 * 
	 * @deprecated should use or override 
	 * projectSetCreated(File, ProjectSetSerializationContext, IProgressMonitor)
	 * instead
	 */
	public void projectSetCreated(File file, Object context, IProgressMonitor monitor) {
		//default is to do nothing
	}
	
	/**
	 * Notify the provider that a project set has been created at path. Only
	 * providers identified as having projects in the project set will be
	 * notified. The project set may or may not be created in a workspace
	 * project (thus may not be a resource).
	 * 
	 * @param file the project set file that was created
	 * @param context
	 * 		the context in which the references are created
	 * 		(not <code>null</code>)
	 * @param monitor a progress monitor
	 * 
	 * @since 3.0
	 */
	public void projectSetCreated(File file, ProjectSetSerializationContext context, IProgressMonitor monitor) {
		// Invoke old method by default
		projectSetCreated(file, context.getShell(), monitor);
	}
	
	/**
	 * For every project in providerProjects, return an opaque
	 * UTF-8 encoded String to act as a reference to that project.
	 * The format of the String is specific to the provider.
	 * The format of the String must be such that
	 * {@link #addToWorkspace(String[], ProjectSetSerializationContext, IProgressMonitor)}
	 * will be able to consume it and load the corresponding project.
	 * <p>
	 * This default implementation simply throws an exception
	 * indicating that no references can be created unless there 
	 * is an IProjectSetSerializer registered for the repository
	 * provider type in which case the operation is delegated to the 
	 * serializer.
	 * Subclasses are expected to override.
	 * 
	 * @since 3.0
	 * 
	 * @param providerProjects
	 * 		an array of projects for which references are needed
	 * 		(not <code>null</code> and contains no <code>null</code>s)
	 * @param context
	 * 		the context in which the references are created
	 * 		(not <code>null</code>)
	 * @param monitor
	 * 		a progress monitor or <code>null</code> if none
	 * @return 
	 * 		an array containing exactly the same number of elements 
	 * 		as the providerProjects argument 
	 * 		where each element is a serialized reference string 
	 * 		uniquely identifying the corresponding the project in the providerProjects array
	 * 		(not <code>null</code> and contains no <code>null</code>s)
	 * @throws TeamException
	 * 		thrown if there is a reference string cannot be created for a project
	 */
	public String[] asReference(
		IProject[] providerProjects,
		ProjectSetSerializationContext context,
		IProgressMonitor monitor)
		throws TeamException {
		
		if (serializer != null) {
			return serializer.asReference(providerProjects, context.getShell(), monitor);
		}
		throw new TeamException(Policy.bind("ProjectSetCapability.0")); //$NON-NLS-1$
	}

	/**
	 * For every String in referenceStrings, load the corresponding project into the workspace.
	 * The opaque strings in referenceStrings are guaranteed to have been previously
	 * produced by {@link #asReference(IProject[], ProjectSetSerializationContext, IProgressMonitor)}.
	 * The confirmOverwrite method is called with an array of projects
	 * for which projects of the same name already exists in the workspace.
	 * <p>
	 * Callers from within a UI context should wrapper a call to this method
	 * inside a WorkspaceModifyOperation so that events generated as a result
	 * of this operation are deferred until the outermost operation
	 * has successfully completed.
	 * <p>
	 * This default implementation simply throws an exception
	 * indicating that no projects can be loaded unless there 
	 * is an IProjectSetSerializer registered for the repository
	 * provider type in which case the operation is delegated to the 
	 * serializer.
	 * Subclasses are expected to override.
	 * 
	 * @since 3.0
	 * 
	 * @param referenceStrings
	 * 		an array of referene strings uniquely identifying the projects
	 * 		(not <code>null</code> and contains no <code>null</code>s)
	 * @param context
	 * 		the context in which the projects are loaded
	 * 		(not <code>null</code>)
	 * @param monitor
	 * 		a progress monitor or <code>null</code> if none
	 * @return IProject[]
	 * 		an array of projects that were loaded
	 * 		excluding those projects already existing and not overwritten
	 * 		(not <code>null</code>, contains no <code>null</code>s)
	 * @throws TeamException
	 * 		thrown if there is a problem loading a project into the workspace.
	 * 		If an exception is thrown, then the workspace is left in an unspecified state
	 * 		where some of the referenced projects may be loaded or partially loaded, and others may not.
	 */
	public IProject[] addToWorkspace(
		String[] referenceStrings,
		ProjectSetSerializationContext context,
		IProgressMonitor monitor)
		throws TeamException {
		
		if (serializer != null) {
			return serializer.addToWorkspace(referenceStrings, context.getFilename(), context.getShell(), monitor);
		}
		throw new TeamException(Policy.bind("ProjectSetCapability.1")); //$NON-NLS-1$
	}
	
	////////////////////////////////////////////////////////////////////////////
	//
	// Internal utility methods for subclasses
	//
	////////////////////////////////////////////////////////////////////////////

	/**
	 * Determine if any of the projects already exist
	 * and confirm which of those projects are to be overwritten.
	 * 
	 * @since 3.0
	 * 
	 * @param context
	 * 		the context in which the projects are loaded
	 * 		(not <code>null</code>)
	 * @param projects 
	 * 		an array of proposed projects to be loaded
	 * 		(not <code>null</code>, contains no <code>null</code>s)
	 * @return 
	 * 		an array of confirmed projects to be loaded
	 * 		or <code>null</code> if the operation is to be canceled.
	 * @throws TeamException
	 */
	protected IProject[] confirmOverwrite(
		ProjectSetSerializationContext context,
		IProject[] projects)
		throws TeamException {
		
		// Build a collection of existing projects
		
		final Collection existingProjects = new ArrayList();
		for (int i = 0; i < projects.length; i++) {
			IProject eachProj = projects[i];
			if (eachProj.exists())
				existingProjects.add(eachProj);
		}
		if (existingProjects.size() == 0)
			return projects;
		
		// Confirm the overwrite
		
		IProject[] confirmed =
			context.confirmOverwrite(
				(IProject[]) existingProjects.toArray(
					new IProject[existingProjects.size()]));
		if (confirmed == null)
			return null;
		if (existingProjects.size() == confirmed.length)
			return projects;
		
		// Return the amended list of projects to be loaded
		
		Collection result = new ArrayList(projects.length);
		result.addAll(Arrays.asList(projects));
		result.removeAll(existingProjects);
		for (int i = 0; i < confirmed.length; i++) {
			IProject eachProj = confirmed[i];
			if (existingProjects.contains(eachProj))
				result.add(eachProj);
		}
		return (IProject[]) result.toArray(new IProject[result.size()]);
	}
	
	/*
	 * Set the serializer to the one registered. The serializer
	 * will be used if subclasses do not override asReference
	 * and addToWorkspace
	 */
	void setSerializer(IProjectSetSerializer serializer) {
		this.serializer = serializer;
	}
}

Back to the top