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

Collapse All | Expand All

(-)src/org/eclipse/pde/internal/core/target/AbstractBundleContainer.java (-2 / +12 lines)
Lines 41-52 Link Here
41
	/**
41
	/**
42
	 * Resolved bundles or <code>null</code> if unresolved
42
	 * Resolved bundles or <code>null</code> if unresolved
43
	 */
43
	 */
44
	private IResolvedBundle[] fBundles;
44
	protected IResolvedBundle[] fBundles;
45
45
46
	/**
46
	/**
47
	 * List of features contained in this bundle container or <code>null</code> if unresolved
47
	 * List of features contained in this bundle container or <code>null</code> if unresolved
48
	 */
48
	 */
49
	private IFeatureModel[] fFeatures;
49
	protected IFeatureModel[] fFeatures;
50
50
51
	/**
51
	/**
52
	 * Status generated when this container was resolved, possibly <code>null</code>
52
	 * Status generated when this container was resolved, possibly <code>null</code>
Lines 551-554 Link Here
551
		}
551
		}
552
		return fVMArgs;
552
		return fVMArgs;
553
	}
553
	}
554
555
	/**
556
	 * Associate this bundle container with the given target.  This allows for the container and 
557
	 * the target to share configuration information etc.  
558
	 * 
559
	 * @param target the target to which this container is being added.
560
	 */
561
	protected void associateWithTarget(ITargetDefinition target) {
562
		// Do nothing by default
563
	}
554
}
564
}
(-)src/org/eclipse/pde/internal/core/target/IUBundleContainer.java (-869 / +234 lines)
Lines 8-38 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Sonatype, Inc. - ongoing development
10
 *     Sonatype, Inc. - ongoing development
11
 *     EclipseSource, Inc. - ongoing development
11
 *******************************************************************************/
12
 *******************************************************************************/
12
package org.eclipse.pde.internal.core.target;
13
package org.eclipse.pde.internal.core.target;
13
14
14
import java.io.File;
15
import java.io.File;
15
import java.net.URI;
16
import java.net.URI;
16
import java.net.URISyntaxException;
17
import java.util.*;
17
import java.util.*;
18
import org.eclipse.core.runtime.*;
18
import org.eclipse.core.runtime.*;
19
import org.eclipse.core.runtime.preferences.IPreferencesService;
20
import org.eclipse.equinox.internal.p2.director.PermissiveSlicer;
19
import org.eclipse.equinox.internal.p2.director.PermissiveSlicer;
21
import org.eclipse.equinox.internal.p2.engine.ProfileMetadataRepository;
20
import org.eclipse.equinox.p2.engine.IProfile;
22
import org.eclipse.equinox.p2.core.IAgentLocation;
23
import org.eclipse.equinox.p2.core.ProvisionException;
24
import org.eclipse.equinox.p2.engine.*;
25
import org.eclipse.equinox.p2.engine.query.IUProfilePropertyQuery;
26
import org.eclipse.equinox.p2.metadata.*;
21
import org.eclipse.equinox.p2.metadata.*;
27
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
28
import org.eclipse.equinox.p2.planner.IPlanner;
29
import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
30
import org.eclipse.equinox.p2.query.*;
22
import org.eclipse.equinox.p2.query.*;
31
import org.eclipse.equinox.p2.repository.*;
32
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
33
import org.eclipse.equinox.p2.repository.artifact.IFileArtifactRepository;
23
import org.eclipse.equinox.p2.repository.artifact.IFileArtifactRepository;
34
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
35
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
36
import org.eclipse.equinox.p2.touchpoint.eclipse.query.OSGiBundleQuery;
24
import org.eclipse.equinox.p2.touchpoint.eclipse.query.OSGiBundleQuery;
37
import org.eclipse.osgi.util.NLS;
25
import org.eclipse.osgi.util.NLS;
38
import org.eclipse.pde.internal.core.PDECore;
26
import org.eclipse.pde.internal.core.PDECore;
Lines 57-120 Link Here
57
	private static final String FEATURE_ID_SUFFIX = ".feature.group"; //$NON-NLS-1$
45
	private static final String FEATURE_ID_SUFFIX = ".feature.group"; //$NON-NLS-1$
58
46
59
	/**
47
	/**
60
	 * IU identifiers.
48
	 * Whether this container must have all required IUs of the selected IUs available and included
49
	 * in the target to resolve successfully.  If this option is true, the planner will be used to resolve
50
	 * otherwise the slicer is used.  The planner can describe any missing requirements as errors.
61
	 */
51
	 */
62
	private String[] fIds;
52
	public static final int INCLUDE_REQUIRED = 1 << 0;
63
53
64
	/**
54
	/**
65
	 * IU versions
55
	 * Whether this container should download and include environment (platform) specific units for all
56
	 * available platforms (vs only the current target definition's environment settings).  Only supported 
57
	 * by the slicer so {@link fIncludeAllRequired} must be turned off for this setting to be used.
66
	 */
58
	 */
67
	private Version[] fVersions;
59
	public static final int INCLUDE_ALL_ENVIRONMENTS = 1 << 1;
68
60
69
	/**
61
	/**
70
	 * Cached IU's referenced by this bundle container, or <code>null</code> if not
62
	 * Whether this container should download and include source bundles for the selected units if the associated
71
	 * resolved.
63
	 * source is available in the repository.
72
	 */
64
	 */
73
	private IInstallableUnit[] fUnits;
65
	public static final int INCLUDE_SOURCE = 1 << 2;
74
66
75
	/**
67
	/**
76
	 * Cached id/version pairs listing the features that were downloaded to the bundle pool during resolution.  <code>null</code> if not resolved.
68
	 * IU identifiers.
77
	 */
69
	 */
78
	private NameVersionDescriptor[] fFeatures;
70
	private String[] fIds;
79
71
80
	/**
72
	/**
81
	 * Repositories to consider, or <code>null</code> if default.
73
	 * IU versions
82
	 */
74
	 */
83
	private URI[] fRepos;
75
	private Version[] fVersions;
84
76
85
	/**
77
	/**
86
	 * Whether this container must have all required IUs of the selected IUs available and included
78
	 * Cached IU's referenced by this bundle container, or <code>null</code> if not
87
	 * in the target to resolve successfully.  If this option is true, the planner will be used to resolve
79
	 * resolved.
88
	 * otherwise the slicer is used.  The planner can describe any missing requirements as errors.
89
	 * <p>
90
	 * <code>true</code> by default
91
	 * </p>
92
	 */
80
	 */
93
	private boolean fIncludeAllRequired = true;
81
	private IInstallableUnit[] fUnits;
94
82
95
	/**
83
	/**
96
	 * Whether this container should download and include environment (platform) specific units for all
84
	 * Repositories to consider, or <code>null</code> if default.
97
	 * available platforms (vs only the current target definition's environment settings).  Only supported 
98
	 * by the slicer so {@link fIncludeAllRequired} must be turned off for this setting to be used.
99
	 * <p>
100
	 * <code>false</code> by default
101
	 * </p>
102
	 */
85
	 */
103
	private boolean fIncludeMultipleEnvironments = false;
86
	private URI[] fRepos;
104
87
105
	/**
88
	/**
106
	 * Whether this container should download and include source bundles for the selected units if the associated
89
	 * A set of bitmask flags that indicate how this container gets elements from its
107
	 * source is available in the repository.
90
	 * associated p2 repository.
108
	 * <p>
109
	 * <code>false</code>by default
110
	 */
91
	 */
111
	private boolean fIncludeSource = false;
92
	private int fFlags;
112
93
113
	/**
94
	/**
114
	 * Constant ID for a root installable unit that is installed into the profile if {@link #fIncludeSource} is set
95
	 *  The p2 synchronizer to use in managing this container.
115
	 * to <code>true</code>.  The source units found in the repository will be set as required IUs on the root unit.
116
	 */
96
	 */
117
	private static final String SOURCE_IU_ID = "org.eclipse.pde.core.target.source.bundles"; //$NON-NLS-1$
97
	private P2TargetUtils fSynchronizer;
118
98
119
	private static final boolean DEBUG_PROFILE;
99
	private static final boolean DEBUG_PROFILE;
120
100
Lines 127-137 Link Here
127
	 * 
107
	 * 
128
	 * @param ids IU identifiers
108
	 * @param ids IU identifiers
129
	 * @param versions IU versions
109
	 * @param versions IU versions
130
	 * @param repositories metadata repositories used to search for IU's or <code>null</code> if
110
	 * @param repositories metadata repositories used to search for IU's or <code>null</code> for default set
131
	 *   default set
111
	 * @param resolutionFlags bitmask of flags to control IU resolution, possible flags are {@link IUBundleContainer#INCLUDE_ALL_ENVIRONMENTS}, {@link IUBundleContainer#INCLUDE_REQUIRED}, {@link IUBundleContainer#INCLUDE_SOURCE}
132
	 */
112
	 */
133
	IUBundleContainer(String[] ids, String[] versions, URI[] repositories) {
113
	IUBundleContainer(String[] ids, String[] versions, URI[] repositories, int resolutionFlags) {
134
		fIds = ids;
114
		fIds = ids;
115
		fFlags = resolutionFlags;
135
		fVersions = new Version[versions.length];
116
		fVersions = new Version[versions.length];
136
		for (int i = 0; i < versions.length; i++) {
117
		for (int i = 0; i < versions.length; i++) {
137
			fVersions[i] = Version.create(versions[i]);
118
			fVersions[i] = Version.create(versions[i]);
Lines 148-159 Link Here
148
	 * Constructs a installable unit bundle container for the specified units.
129
	 * Constructs a installable unit bundle container for the specified units.
149
	 * 
130
	 * 
150
	 * @param units IU's
131
	 * @param units IU's
151
	 * @param repositories metadata repositories used to search for IU's or <code>null</code> if
132
	 * @param repositories metadata repositories used to search for IU's or <code>null</code> for default set
152
	 *   default set
133
	 * @param resolutionFlags bitmask of flags to control IU resolution, possible flags are {@link IUBundleContainer#INCLUDE_ALL_ENVIRONMENTS}, {@link IUBundleContainer#INCLUDE_REQUIRED}, {@link IUBundleContainer#INCLUDE_SOURCE}
153
	 */
134
	 */
154
	IUBundleContainer(IInstallableUnit[] units, URI[] repositories) {
135
	IUBundleContainer(IInstallableUnit[] units, URI[] repositories, int resolutionFlags) {
155
		fUnits = units;
156
		fIds = new String[units.length];
136
		fIds = new String[units.length];
137
		fFlags = resolutionFlags;
157
		fVersions = new Version[units.length];
138
		fVersions = new Version[units.length];
158
		for (int i = 0; i < units.length; i++) {
139
		for (int i = 0; i < units.length; i++) {
159
			fIds[i] = units[i].getId();
140
			fIds[i] = units[i].getId();
Lines 184-792 Link Here
184
	 * @see org.eclipse.pde.internal.core.target.AbstractBundleContainer#resolveFeatures(org.eclipse.pde.internal.core.target.provisional.ITargetDefinition, org.eclipse.core.runtime.IProgressMonitor)
165
	 * @see org.eclipse.pde.internal.core.target.AbstractBundleContainer#resolveFeatures(org.eclipse.pde.internal.core.target.provisional.ITargetDefinition, org.eclipse.core.runtime.IProgressMonitor)
185
	 */
166
	 */
186
	protected IFeatureModel[] resolveFeatures(ITargetDefinition definition, IProgressMonitor monitor) throws CoreException {
167
	protected IFeatureModel[] resolveFeatures(ITargetDefinition definition, IProgressMonitor monitor) throws CoreException {
187
		if (fFeatures == null || fFeatures.length == 0 || !(definition instanceof TargetDefinition)) {
168
		fSynchronizer.synchronize(monitor);
169
		return fFeatures;
170
	}
171
172
	/**
173
	 * Update this container's cache of feature objects based on the given profile.
174
	 * NOTE: this method expects the synchronizer to be synchronized and is called
175
	 * as a result of a synchronization operation.
176
	 */
177
	IFeatureModel[] cacheFeatures() throws CoreException {
178
		Set features = new HashSet();
179
		for (int i = 0; i < fUnits.length; i++) {
180
			IInstallableUnit unit = fUnits[i];
181
			String id = unit.getId();
182
			// if theIU was explicitly added and the naming convention says it is a feature, then add it. 
183
			// This is less than optimal but there is no clear way of identifying an IU as a feature.
184
			if (isRoot(id, unit.getVersion()) && id.endsWith(FEATURE_ID_SUFFIX)) {
185
				id = id.substring(0, id.length() - FEATURE_ID_SUFFIX.length());
186
				String version = unit.getVersion().toString();
187
				features.add(new NameVersionDescriptor(id, version, NameVersionDescriptor.TYPE_FEATURE));
188
			}
189
		}
190
		if (features.isEmpty()) {
188
			return new IFeatureModel[0];
191
			return new IFeatureModel[0];
189
		}
192
		}
190
193
191
		// Note: By creating a map of the container features, we are limiting the user to only one version of a feature in this container
194
		// Now get feature models for all known features
192
195
		TargetDefinition definition = (TargetDefinition) fSynchronizer.getTargetDefinition();
193
		// Get all the features in the bundle pool
196
		IFeatureModel[] allFeatures = definition.getFeatureModels(getLocation(false), new NullProgressMonitor());
194
		IFeatureModel[] allFeatures = ((TargetDefinition) definition).getFeatureModels(getLocation(false), monitor);
195
196
		// Create a map of the container features for quick lookups
197
		HashMap containerFeatures = new HashMap();
198
		for (int i = 0; i < fFeatures.length; i++) {
199
			containerFeatures.put(fFeatures[i].getId(), fFeatures[i]);
200
		}
201
197
202
		List includedFeatures = new ArrayList();
198
		// Build a final set of the models for the features in the profile.
199
		List result = new ArrayList();
203
		for (int i = 0; i < allFeatures.length; i++) {
200
		for (int i = 0; i < allFeatures.length; i++) {
204
			NameVersionDescriptor candidate = (NameVersionDescriptor) containerFeatures.get(allFeatures[i].getFeature().getId());
201
			NameVersionDescriptor candidate = new NameVersionDescriptor(allFeatures[i].getFeature().getId(), allFeatures[i].getFeature().getVersion(), NameVersionDescriptor.TYPE_FEATURE);
205
			if (candidate != null) {
202
			if (features.contains(candidate)) {
206
				if (candidate.getVersion().equals(allFeatures[i].getFeature().getVersion())) {
203
				result.add(allFeatures[i]);
207
					includedFeatures.add(allFeatures[i]);
208
				}
209
			}
204
			}
210
		}
205
		}
211
		return (IFeatureModel[]) includedFeatures.toArray(new IFeatureModel[includedFeatures.size()]);
206
		fFeatures = (IFeatureModel[]) result.toArray(new IFeatureModel[result.size()]);
207
		return fFeatures;
208
	}
209
210
	private boolean isRoot(String id, Version version) {
211
		for (int i = 0; i < fIds.length; i++) {
212
			String fid = fIds[i];
213
			if (fid.equals(id) && fVersions[i].equals(version))
214
				return true;
215
		}
216
		return false;
212
	}
217
	}
213
218
214
	/* (non-Javadoc)
219
	/* (non-Javadoc)
215
	 * @see org.eclipse.pde.internal.core.target.impl.AbstractBundleContainer#resolveBundles(org.eclipse.pde.internal.core.target.provisional.ITargetDefinition, org.eclipse.core.runtime.IProgressMonitor)
220
	 * @see org.eclipse.pde.internal.core.target.impl.AbstractBundleContainer#resolveBundles(org.eclipse.pde.internal.core.target.provisional.ITargetDefinition, org.eclipse.core.runtime.IProgressMonitor)
216
	 */
221
	 */
217
	protected IResolvedBundle[] resolveBundles(ITargetDefinition definition, IProgressMonitor monitor) throws CoreException {
222
	protected IResolvedBundle[] resolveBundles(ITargetDefinition definition, IProgressMonitor monitor) throws CoreException {
218
		// Resolving may change the included features, clear the cached values
223
		fSynchronizer.synchronize(monitor);
219
		fFeatures = null;
224
		return fBundles;
220
221
		SubMonitor subMon = SubMonitor.convert(monitor, 100);
222
223
		// Attempt to restore from the profile first, as it is local and faster
224
		IResolvedBundle[] result = resolveWithProfile(definition, subMon.newChild(25));
225
		if (result != null) {
226
			subMon.done();
227
			return result;
228
		}
229
230
		// Unable to load from profile, resolve normally
231
		try {
232
			if (fIncludeAllRequired) {
233
				result = resolveWithPlanner(definition, subMon.newChild(75));
234
			} else {
235
				result = resolveWithSlicer(definition, subMon.newChild(75));
236
			}
237
			// If there is a problem generating the profile, delete it so it doesn't get used by #resolveWithProfile()
238
			if (result == null || result.length == 0 || subMon.isCanceled()) {
239
				AbstractTargetHandle handle = ((AbstractTargetHandle) definition.getHandle());
240
				P2TargetUtils.deleteProfile(handle);
241
			}
242
			return result;
243
		} catch (CoreException e) {
244
			AbstractTargetHandle handle = ((AbstractTargetHandle) definition.getHandle());
245
			P2TargetUtils.deleteProfile(handle);
246
			throw e;
247
		}
248
249
	}
225
	}
250
226
251
	/**
227
	/**
252
	 * Used to resolve the contents of this container if the container has been resolved and saved to a profile file.  If the
228
	 * Update this container's cache of top level IUs based on the given profile.
253
	 * profile contains the correct bundles, there is no need to do a full resolve.  If this method has a problem (missing
229
	 * NOTE: this method expects the synchronizer to be synchronized and is called
254
	 * file, unable to compute all dependent bundles), this method will return <code>null</code> and the caller should 
230
	 * as a result of a synchronization operation.
255
	 * use {@link #resolveWithPlanner(ITargetDefinition, IProgressMonitor)} or {@link #resolveWithSlicer(ITargetDefinition, IProgressMonitor)} 
231
	 */
256
	 * to do a full resolve.
232
	IInstallableUnit[] cacheIUs() throws CoreException {
257
	 * 
233
		IProfile profile = fSynchronizer.getProfile();
258
	 * @param definition definition being resolved
234
		ArrayList result = new ArrayList();
259
	 * @param monitor for reporting progress
260
	 * @return set of bundles included in this container or <code>null</code> if the profile is out of date
261
	 * @throws CoreException if an unexpected problem occurs trying to read from the profile
262
	 */
263
	private IResolvedBundle[] resolveWithProfile(ITargetDefinition definition, IProgressMonitor monitor) throws CoreException {
264
		if (DEBUG_PROFILE) {
265
			System.out.println("Target resolution using profile (" + definition.getName() + ")"); //$NON-NLS-1$//$NON-NLS-2$
266
		}
267
268
		IProfile profile = P2TargetUtils.getProfile(definition);
269
		if (profile == null) {
270
			if (DEBUG_PROFILE) {
271
				System.out.println("No profile found"); //$NON-NLS-1$
272
			}
273
			return null;
274
		}
275
276
		SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.IUBundleContainer_LoadingFromProfileJob, 20);
277
278
		// Always create our own units because the slicer will return existing units even though the profile is empty
279
		if (DEBUG_PROFILE) {
280
			System.out.print("Required Units: "); //$NON-NLS-1$
281
			for (int i = 0; i < fIds.length; i++) {
282
				System.out.print(fIds[i] + ", "); //$NON-NLS-1$
283
			}
284
			System.out.println();
285
		}
286
287
		fUnits = new IInstallableUnit[fIds.length];
288
		for (int i = 0; i < fIds.length; i++) {
235
		for (int i = 0; i < fIds.length; i++) {
289
			IQuery query = QueryUtil.createIUQuery(fIds[i], fVersions[i]);
236
			IQuery query = QueryUtil.createIUQuery(fIds[i], fVersions[i]);
290
			IQueryResult queryResult = profile.query(query, null);
237
			IQueryResult queryResult = profile.query(query, null);
291
			if (queryResult.isEmpty()) {
238
			if (queryResult.isEmpty())
292
				if (DEBUG_PROFILE) {
239
				throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, NLS.bind(Messages.IUBundleContainer_1, fIds[i])));
293
					System.out.println("Required unit not found in profile: " + fIds[i]); //$NON-NLS-1$
240
			result.add(queryResult.iterator().next());
294
				}
295
				fUnits = null;
296
				return null;
297
			}
298
			fUnits[i] = (IInstallableUnit) queryResult.iterator().next();
299
		}
300
		// check that the include source flag matches what the profile represents
301
		if (fIncludeSource != (getCurrentSourceIU(profile) != null))
302
			return null;
303
304
		// OK.  Everything looks good.  Now gather the features and bundles and be done.
305
		ResolvedBundle[] resolvedBundles = updateAfterResolve(profile, definition);
306
307
		subMonitor.worked(10);
308
		subMonitor.done();
309
		if (DEBUG_PROFILE) {
310
			if (resolvedBundles == null || resolvedBundles.length == 0)
311
				System.out.println("No bundles loaded from profile"); //$NON-NLS-1$
312
			else
313
				System.out.println("Loading from profile successful. " + resolvedBundles.length + " bundles found"); //$NON-NLS-1$ //$NON-NLS-2$
314
			System.out.println();
315
		}
316
		return resolvedBundles;
317
	}
318
319
	/**
320
	 * Used to resolve the contents of this container if the user is including all required software.  The p2 planner is used
321
	 * to determine the complete set of IUs required to run the selected software.  If all requirements are met, the bundles
322
	 * are downloaded from the repository into the bundle pool and added to the target definition.
323
	 * 
324
	 * @param definition definition being resolved
325
	 * @param monitor for reporting progress
326
	 * @return set of bundles included in this container
327
	 * @throws CoreException if there is a problem with the requirements or there is a problem downloading
328
	 */
329
	private IResolvedBundle[] resolveWithPlanner(ITargetDefinition definition, IProgressMonitor monitor) throws CoreException {
330
		SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 10);
331
		subMonitor.beginTask(Messages.IUBundleContainer_0, 200);
332
333
		// retrieve profile
334
		IProfile profile = P2TargetUtils.getProfile(definition);
335
		profile.getTimestamp();
336
		subMonitor.worked(10);
337
338
		if (subMonitor.isCanceled()) {
339
			return new IResolvedBundle[0];
340
		}
341
342
		// resolve IUs
343
		IInstallableUnit[] units = getInstallableUnits(profile);
344
345
		if (subMonitor.isCanceled()) {
346
			return new IResolvedBundle[0];
347
		}
348
349
		// create the provisioning plan
350
		IPlanner planner = P2TargetUtils.getPlanner();
351
		IProfileChangeRequest request = planner.createChangeRequest(profile);
352
		// first remove everything that was explicitly installed.  Then add it back.  This has the net effect of 
353
		// removing everything that is no longer needed.
354
		computeRemovals(profile, request, units);
355
		request.addAll(Arrays.asList(units));
356
		for (int i = 0; i < units.length; i++) {
357
			IInstallableUnit unit = units[i];
358
			request.setInstallableUnitProfileProperty(unit, P2TargetUtils.PROP_INSTALLED_IU, Boolean.toString(true));
359
		}
360
361
		ProvisioningContext context = new ProvisioningContext(P2TargetUtils.getAgent());
362
		context.setMetadataRepositories(resolveRepositories());
363
		context.setArtifactRepositories(resolveArtifactRepositories());
364
365
		if (subMonitor.isCanceled()) {
366
			return new IResolvedBundle[0];
367
		}
368
369
		IProvisioningPlan plan = planner.getProvisioningPlan(request, context, new SubProgressMonitor(subMonitor, 20));
370
		IStatus status = plan.getStatus();
371
		if (!status.isOK()) {
372
			throw new CoreException(status);
373
		}
374
		IProvisioningPlan installerPlan = plan.getInstallerPlan();
375
		if (installerPlan != null) {
376
			// this plan requires an update to the installer first, log the fact and attempt
377
			// to continue, we don't want to update the running SDK while provisioning a target
378
			PDECore.log(new Status(IStatus.INFO, PDECore.PLUGIN_ID, Messages.IUBundleContainer_6));
379
		}
380
		subMonitor.worked(10);
381
382
		if (subMonitor.isCanceled()) {
383
			return new IResolvedBundle[0];
384
		}
385
386
		// execute the provisioning plan
387
		IPhaseSet phases = PhaseSetFactory.createDefaultPhaseSetExcluding(new String[] {PhaseSetFactory.PHASE_CHECK_TRUST, PhaseSetFactory.PHASE_CONFIGURE, PhaseSetFactory.PHASE_UNCONFIGURE});
388
		IEngine engine = P2TargetUtils.getEngine();
389
		plan.setProfileProperty(P2TargetUtils.PROP_PROVISION_MODE, TargetDefinitionPersistenceHelper.MODE_PLANNER);
390
		plan.setProfileProperty(P2TargetUtils.PROP_ALL_ENVIRONMENTS, Boolean.toString(false));
391
		IStatus result = engine.perform(plan, phases, new SubProgressMonitor(subMonitor, 140));
392
393
		if (subMonitor.isCanceled()) {
394
			return new IResolvedBundle[0];
395
		}
396
		if (!result.isOK()) {
397
			throw new CoreException(result);
398
		}
399
400
		// Now that we have a plan with all the binary and explicit bundles, do a second pass and add 
401
		// in all the source.
402
		try {
403
			planInSourceBundles(profile, context, subMonitor);
404
		} catch (CoreException e) {
405
			// XXX Review required: is adding in the source critical or optional?
406
			// We failed adding in the source so remove the intermediate profile and rethrow
407
			P2TargetUtils.getProfileRegistry().removeProfile(profile.getProfileId(), profile.getTimestamp());
408
			throw e;
409
		}
410
411
		ResolvedBundle[] resolvedBundles = updateAfterResolve(profile, definition);
412
		subMonitor.worked(10);
413
		subMonitor.done();
414
		return resolvedBundles;
415
	}
416
417
	/** 
418
	 * Update the given change request to remove anything that was explicitly installed
419
	 * including the internal source IU.  
420
	 */
421
	private void computeRemovals(IProfile profile, IProfileChangeRequest request, IInstallableUnit[] units) {
422
		// if include source is off then ensure that the source IU is removed.
423
		if (!fIncludeSource) {
424
			IInstallableUnit sourceIU = getCurrentSourceIU(profile);
425
			if (sourceIU != null)
426
				request.remove(sourceIU);
427
		}
428
		// remove everything that is marked as roots.  The plan will have the new roots added in anyway.
429
		IQuery query = new IUProfilePropertyQuery(P2TargetUtils.PROP_INSTALLED_IU, Boolean.toString(true));
430
		IQueryResult installedIUs = profile.query(query, null);
431
		request.removeAll(installedIUs.toSet());
432
	}
433
434
	// run a second pass of the planner to add in the source bundles for everything that's
435
	// in the current profile.
436
	private void planInSourceBundles(IProfile profile, ProvisioningContext context, IProgressMonitor monitor) throws CoreException {
437
		if (!fIncludeSource)
438
			return;
439
440
		SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 10);
441
		subMonitor.beginTask(Messages.IUBundleContainer_ProvisioningSourceBundles, 200);
442
443
		// create an IU that optionally and greedily requires the related source bundles.
444
		// Completely replace any source IU that may already be in place
445
		IInstallableUnit currentSourceIU = getCurrentSourceIU(profile);
446
447
		// determine the new version number.  start at 1
448
		Version sourceVersion = Version.createOSGi(1, 0, 0);
449
		if (currentSourceIU != null) {
450
			Integer major = (Integer) currentSourceIU.getVersion().getSegment(0);
451
			sourceVersion = Version.createOSGi(major.intValue() + 1, 0, 0);
452
		}
453
		IInstallableUnit sourceIU = createSourceIU(profile, sourceVersion);
454
455
		// call the planner again to add in the new source IU and all available source bundles
456
		IPlanner planner = P2TargetUtils.getPlanner();
457
		IProfileChangeRequest request = planner.createChangeRequest(profile);
458
		if (currentSourceIU != null)
459
			request.remove(currentSourceIU);
460
		request.add(sourceIU);
461
		IProvisioningPlan plan = planner.getProvisioningPlan(request, context, new SubProgressMonitor(subMonitor, 20));
462
		IStatus status = plan.getStatus();
463
		if (!status.isOK()) {
464
			throw new CoreException(status);
465
		}
466
		if (subMonitor.isCanceled()) {
467
			return;
468
		}
469
470
		long oldTimestamp = profile.getTimestamp();
471
472
		// execute the provisioning plan
473
		IPhaseSet phases = PhaseSetFactory.createDefaultPhaseSetExcluding(new String[] {PhaseSetFactory.PHASE_CHECK_TRUST, PhaseSetFactory.PHASE_CONFIGURE, PhaseSetFactory.PHASE_UNCONFIGURE, PhaseSetFactory.PHASE_UNINSTALL});
474
		IEngine engine = P2TargetUtils.getEngine();
475
		plan.setProfileProperty(P2TargetUtils.PROP_PROVISION_MODE, TargetDefinitionPersistenceHelper.MODE_PLANNER);
476
		plan.setProfileProperty(P2TargetUtils.PROP_ALL_ENVIRONMENTS, Boolean.toString(false));
477
		IStatus result = engine.perform(plan, phases, new SubProgressMonitor(subMonitor, 140));
478
479
		if (subMonitor.isCanceled()) {
480
			return;
481
		}
482
		if (!result.isOK()) {
483
			throw new CoreException(result);
484
		}
485
486
		// remove the old (intermediate) profile version now we have a new one with source.
487
		P2TargetUtils.getProfileRegistry().removeProfile(profile.getProfileId(), oldTimestamp);
488
		subMonitor.worked(10);
489
		subMonitor.done();
490
	}
491
492
	// Create and return an IU that has optional and greedy requirements on all source bundles
493
	// related to bundle IUs in the given queryable. 
494
	/**
495
	 * Creates and returns an IU that has optional and greedy requirements on all source bundles
496
	 * related to bundle IUs in the given queryable.
497
	 * @param queryable location to search for source bundle IUs
498
	 * @param iuVersion version to set on the returned installable unit
499
	 * @return a new installable unit with requirements on the available source IUs
500
	 */
501
	private IInstallableUnit createSourceIU(IQueryable queryable, Version iuVersion) {
502
		// compute the set of source bundles we could possibly need for the bundles in the profile
503
		IRequirement bundleRequirement = MetadataFactory.createRequirement("org.eclipse.equinox.p2.eclipse.type", "bundle", null, null, false, false, false); //$NON-NLS-1$ //$NON-NLS-2$
504
		IQueryResult profileIUs = queryable.query(QueryUtil.createIUAnyQuery(), null);
505
		ArrayList requirements = new ArrayList();
506
		for (Iterator i = profileIUs.iterator(); i.hasNext();) {
507
			IInstallableUnit profileIU = (IInstallableUnit) i.next();
508
			if (profileIU.satisfies(bundleRequirement)) {
509
				String id = profileIU.getId() + ".source"; //$NON-NLS-1$
510
				Version version = profileIU.getVersion();
511
				VersionRange range = new VersionRange(version, true, version, true);
512
				IRequirement sourceRequirement = MetadataFactory.createRequirement("osgi.bundle", id, range, null, true, false, true); //$NON-NLS-1$
513
				requirements.add(sourceRequirement);
514
			}
515
		}
241
		}
516
242
		fUnits = (IInstallableUnit[]) result.toArray(new IInstallableUnit[result.size()]);
517
		InstallableUnitDescription sourceDescription = new MetadataFactory.InstallableUnitDescription();
243
		return fUnits;
518
		sourceDescription.setSingleton(true);
519
		sourceDescription.setId(SOURCE_IU_ID);
520
		sourceDescription.setVersion(iuVersion);
521
		sourceDescription.addRequirements(requirements);
522
		IProvidedCapability capability = MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, SOURCE_IU_ID, iuVersion);
523
		sourceDescription.setCapabilities(new IProvidedCapability[] {capability});
524
		return MetadataFactory.createInstallableUnit(sourceDescription);
525
	}
526
527
	/**
528
	 * Lookup and return the source IU in the given queryable or <code>null</code> if not found.
529
	 * @param queryable location to look for source IUs
530
	 * @return the source IU or <code>null</code>
531
	 */
532
	private IInstallableUnit getCurrentSourceIU(IQueryable queryable) {
533
		IQuery query = QueryUtil.createIUQuery(SOURCE_IU_ID);
534
		IQueryResult list = queryable.query(query, null);
535
		IInstallableUnit currentSourceIU = null;
536
		if (!list.isEmpty())
537
			currentSourceIU = (IInstallableUnit) list.iterator().next();
538
		return currentSourceIU;
539
	}
244
	}
540
245
541
	/**
246
	/**
542
	 * Used to resolve the contents of this container when the user has chosen to manage the dependencies in the target
247
	 * Update this container's cache of bundle objects based on the given profile.
543
	 * themselves.  The selected IUs and any required software that can be found will be retrieved from the repositories 
248
	 * NOTE: this method expects the synchronizer to be synchronized and is called
544
	 * and added to the target.  Any missing required software will be ignored.
249
	 * as a result of a synchronization operation.
545
	 * 
250
	 */
546
	 * @param definition definition being resolved
251
	IResolvedBundle[] cacheBundles() throws CoreException {
547
	 * @param monitor for reporting progress
252
		// slice the profile to find the bundles attributed to this container.
548
	 * @return set of resolved bundles included in this container
253
		// Look only for strict dependencies if we are using the slicer.
549
	 * @throws CoreException if there is a problem interacting with the repositories
254
		// We can always consider all platforms since the profile wouldn't contain it if it was not interesting
550
	 */
255
		boolean onlyStrict = !fSynchronizer.getIncludeAllRequired();
551
	private IResolvedBundle[] resolveWithSlicer(ITargetDefinition definition, IProgressMonitor monitor) throws CoreException {
256
		IProfile metadata = fSynchronizer.getProfile();
552
		SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 10);
257
		PermissiveSlicer slicer = new PermissiveSlicer(metadata, new HashMap(), true, false, true, onlyStrict, false);
553
		subMonitor.beginTask(Messages.IUBundleContainer_0, 180);
258
		IQueryable slice = slicer.slice(fUnits, new NullProgressMonitor());
554
555
		// retrieve profile
556
		IProfile profile = P2TargetUtils.getProfile(definition);
557
		subMonitor.worked(10);
558
559
		if (subMonitor.isCanceled()) {
560
			return new IResolvedBundle[0];
561
		}
562
563
		// resolve IUs
564
		IInstallableUnit[] units = getInstallableUnits(profile);
565
566
		if (subMonitor.isCanceled()) {
567
			return new IResolvedBundle[0];
568
		}
569
570
		URI[] repositories = resolveRepositories();
571
		int repoCount = repositories.length;
572
		if (repoCount == 0) {
573
			return new IResolvedBundle[0];
574
		}
575
576
		IProgressMonitor loadMonitor = new SubProgressMonitor(subMonitor, 10);
577
		loadMonitor.beginTask(null, repoCount * 10);
578
		List metadataRepos = new ArrayList(repoCount);
579
		MultiStatus repoStatus = new MultiStatus(PDECore.PLUGIN_ID, 0, Messages.IUBundleContainer_ProblemsLoadingRepositories, null);
580
		IMetadataRepositoryManager manager = P2TargetUtils.getRepoManager();
581
		for (int i = 0; i < repoCount; ++i) {
582
			try {
583
				IMetadataRepository repo = manager.loadRepository(repositories[i], new SubProgressMonitor(loadMonitor, 10));
584
				metadataRepos.add(repo);
585
			} catch (ProvisionException e) {
586
				repoStatus.add(e.getStatus());
587
			}
588
		}
589
		loadMonitor.done();
590
591
		IQueryable allMetadata;
592
		if (metadataRepos.size() == 0) {
593
			throw new CoreException(repoStatus);
594
		} else if (metadataRepos.size() == 1) {
595
			allMetadata = (IQueryable) metadataRepos.get(0);
596
		} else {
597
			allMetadata = QueryUtil.compoundQueryable(metadataRepos);
598
		}
599
600
		// do an initial slice to add everything the user requested
601
		IQueryResult queryResult = slice(units, allMetadata, definition, subMonitor);
602
		if (subMonitor.isCanceled() || queryResult == null || queryResult.isEmpty()) {
603
			return new IResolvedBundle[0];
604
		}
605
606
		// If we are including source then create a source IU to bring in the relevant source
607
		// bundles and run the slicer again.
608
		if (fIncludeSource) {
609
			// Build an IU that represents all the source bundles and slice again to add them in if available
610
			IInstallableUnit sourceIU = createSourceIU(queryResult, Version.createOSGi(1, 0, 0));
611
			IInstallableUnit[] units2 = new IInstallableUnit[units.length + 1];
612
			System.arraycopy(units, 0, units2, 0, units.length);
613
			units2[units.length] = sourceIU;
614
615
			queryResult = slice(units2, allMetadata, definition, subMonitor);
616
			if (subMonitor.isCanceled() || queryResult == null || queryResult.isEmpty()) {
617
				return new IResolvedBundle[0];
618
			}
619
		}
620
621
		IEngine engine = P2TargetUtils.getEngine();
622
		ProvisioningContext context = new ProvisioningContext(P2TargetUtils.getAgent());
623
		context.setMetadataRepositories(repositories);
624
		context.setArtifactRepositories(resolveArtifactRepositories());
625
		IProvisioningPlan plan = engine.createPlan(profile, context);
626
627
		Set newSet = queryResult.toSet();
628
		Iterator itor = newSet.iterator();
629
		while (itor.hasNext()) {
630
			plan.addInstallableUnit((IInstallableUnit) itor.next());
631
		}
632
		for (int i = 0; i < units.length; i++) {
633
			IInstallableUnit unit = units[i];
634
			plan.setInstallableUnitProfileProperty(unit, P2TargetUtils.PROP_INSTALLED_IU, Boolean.toString(true));
635
		}
636
637
		// remove all units that are in the current profile but not in the new slice
638
		Set toRemove = profile.query(QueryUtil.ALL_UNITS, null).toSet();
639
		toRemove.removeAll(newSet);
640
		for (Iterator i = toRemove.iterator(); i.hasNext();) {
641
			plan.removeInstallableUnit((IInstallableUnit) i.next());
642
		}
643
644
		plan.setProfileProperty(P2TargetUtils.PROP_PROVISION_MODE, TargetDefinitionPersistenceHelper.MODE_SLICER);
645
		plan.setProfileProperty(P2TargetUtils.PROP_ALL_ENVIRONMENTS, Boolean.toString(getIncludeAllEnvironments()));
646
647
		// execute the provisioning plan
648
		IPhaseSet phases = PhaseSetFactory.createDefaultPhaseSetExcluding(new String[] {PhaseSetFactory.PHASE_CHECK_TRUST, PhaseSetFactory.PHASE_CONFIGURE, PhaseSetFactory.PHASE_UNCONFIGURE});
649
		IStatus result = engine.perform(plan, phases, new SubProgressMonitor(subMonitor, 140));
650
651
		if (subMonitor.isCanceled()) {
652
			return new IResolvedBundle[0];
653
		}
654
		if (!result.isOK()) {
655
			throw new CoreException(result);
656
		}
657
658
		ResolvedBundle[] resolvedBundles = updateAfterResolve(profile, definition);
659
660
		subMonitor.worked(10);
661
		subMonitor.done();
662
		return resolvedBundles;
663
	}
664
665
	private ResolvedBundle[] updateAfterResolve(IProfile profile, ITargetDefinition definition) throws CoreException {
666
		// Cache the feature list
667
		queryForFeatures(profile);
668
259
669
		// query for bundles
260
		// query for bundles
670
		IFileArtifactRepository repository = null;
261
		IFileArtifactRepository artifacts = null;
671
		try {
262
		try {
672
			repository = P2TargetUtils.getBundlePool(profile);
263
			artifacts = P2TargetUtils.getBundlePool();
673
		} catch (CoreException e) {
264
		} catch (CoreException e) {
674
			if (DEBUG_PROFILE) {
265
			if (DEBUG_PROFILE) {
675
				System.out.println("Bundle pool repository could not be loaded"); //$NON-NLS-1$
266
				System.out.println("Bundle pool repository could not be loaded"); //$NON-NLS-1$
676
			}
267
			}
677
			return null;
268
			return fBundles = null;
678
		}
269
		}
679
270
680
		Map bundles = generateResolvedBundles(profile, repository, true);
271
		Map bundles = generateResolvedBundles(slice, metadata, artifacts);
681
		if (bundles == null || bundles.isEmpty()) {
272
		if (bundles.isEmpty()) {
682
			if (DEBUG_PROFILE) {
273
			if (DEBUG_PROFILE) {
683
				System.out.println("Profile does not contain any bundles or artifacts were missing"); //$NON-NLS-1$
274
				System.out.println("Profile does not contain any bundles or artifacts were missing"); //$NON-NLS-1$
684
			}
275
			}
685
			return null;
276
			return fBundles = null;
686
		}
277
		}
687
278
688
		removeDuplicateBundles(definition, bundles);
279
		fBundles = (ResolvedBundle[]) bundles.values().toArray(new ResolvedBundle[bundles.size()]);
689
		if (bundles.isEmpty()) {
280
		return fBundles;
690
			return null;
691
		}
692
693
		return (ResolvedBundle[]) bundles.values().toArray(new ResolvedBundle[bundles.size()]);
694
	}
695
696
	private IQueryResult slice(IInstallableUnit[] units, IQueryable allMetadata, ITargetDefinition definition, SubProgressMonitor subMonitor) throws CoreException {
697
		// slice IUs and all prerequisites
698
		PermissiveSlicer slicer = null;
699
		if (getIncludeAllEnvironments()) {
700
			slicer = new PermissiveSlicer(allMetadata, new HashMap(), true, false, true, true, false);
701
		} else {
702
			Map props = new HashMap();
703
			props.put("osgi.os", definition.getOS() != null ? definition.getOS() : Platform.getOS()); //$NON-NLS-1$
704
			props.put("osgi.ws", definition.getWS() != null ? definition.getWS() : Platform.getWS()); //$NON-NLS-1$
705
			props.put("osgi.arch", definition.getArch() != null ? definition.getArch() : Platform.getOSArch()); //$NON-NLS-1$
706
			props.put("osgi.nl", definition.getNL() != null ? definition.getNL() : Platform.getNL()); //$NON-NLS-1$
707
			props.put(IProfile.PROP_INSTALL_FEATURES, Boolean.TRUE.toString());
708
			slicer = new PermissiveSlicer(allMetadata, props, true, false, false, true, false);
709
		}
710
		IQueryable slice = slicer.slice(units, new SubProgressMonitor(subMonitor, 10));
711
		if (!slicer.getStatus().isOK()) {
712
			throw new CoreException(slicer.getStatus());
713
		}
714
		IQueryResult queryResult = null;
715
		if (slice != null)
716
			queryResult = slice.query(QueryUtil.createIUAnyQuery(), new SubProgressMonitor(subMonitor, 10));
717
		return queryResult;
718
	}
719
720
	/**
721
	 * Queries the given given queryable and finds all feature group IUs.  The feature id/versions of the features
722
	 * are cached in {@link #fFeatures}.
723
	 * 
724
	 * @param queryable profile/slicer/etc. to query for features
725
	 */
726
	private void queryForFeatures(IQueryable queryable) {
727
		// Query for features, cache the result for calls to resolveFeatures()
728
		// Get any IU with the group property, this will return any feature groups
729
		IQuery featureQuery = QueryUtil.createMatchQuery("properties[$0] == $1", new Object[] {MetadataFactory.InstallableUnitDescription.PROP_TYPE_GROUP, Boolean.TRUE.toString()}); //$NON-NLS-1$
730
		IQueryResult featureResult = queryable.query(featureQuery, null);
731
		List features = new ArrayList();
732
		for (Iterator iterator = featureResult.iterator(); iterator.hasNext();) {
733
			IInstallableUnit unit = (IInstallableUnit) iterator.next();
734
			String id = unit.getId();
735
			if (id.endsWith(FEATURE_ID_SUFFIX)) {
736
				id = id.substring(0, id.length() - FEATURE_ID_SUFFIX.length());
737
			}
738
			String version = unit.getVersion().toString();
739
			features.add(new NameVersionDescriptor(id, version, NameVersionDescriptor.TYPE_FEATURE));
740
		}
741
		fFeatures = (NameVersionDescriptor[]) features.toArray(new NameVersionDescriptor[features.size()]);
742
	}
281
	}
743
282
744
	/**
283
	/*
745
	 * Returns the IU's this container references. Checks in the profile first to avoid
284
	 * Respond to the notification that the synchronizer associated with this container has changed
746
	 * going out to repositories.
285
	 * This is a callback method used by the synchronizer.
747
	 * 
286
	 * It should NOT be called any other time.
748
	 * @param profile profile to check first
749
	 * @return IU's
750
	 * @exception CoreException if unable to retrieve IU's
751
	 */
287
	 */
752
	public synchronized IInstallableUnit[] getInstallableUnits(IProfile profile) throws CoreException {
288
	void synchronizerChanged() throws CoreException {
753
		if (fUnits == null) {
289
		// cache the IUs first as they are used to slice the profile for the other caches.
754
			fUnits = new IInstallableUnit[fIds.length];
290
		cacheIUs();
755
			for (int i = 0; i < fIds.length; i++) {
291
		cacheBundles();
756
				IQuery query = QueryUtil.createIUQuery(fIds[i], fVersions[i]);
292
		cacheFeatures();
757
				IQueryResult queryResult = profile.query(query, null);
758
				if (queryResult.isEmpty()) {
759
					// try repositories
760
					URI[] repositories = resolveRepositories();
761
					for (int j = 0; j < repositories.length; j++) {
762
						try {
763
							IMetadataRepository repository = P2TargetUtils.getRepository(repositories[j]);
764
							queryResult = repository.query(query, null);
765
							if (!queryResult.isEmpty()) {
766
								break;
767
							}
768
						} catch (ProvisionException e) {
769
							// Ignore and move on to the next site
770
						}
771
					}
772
				}
773
				if (queryResult.isEmpty()) {
774
					// not found
775
					fUnits = null;
776
					throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, NLS.bind(Messages.IUBundleContainer_1, fIds[i])));
777
				}
778
				fUnits[i] = (IInstallableUnit) queryResult.iterator().next();
779
			}
780
		}
781
		return fUnits;
782
	}
783
784
	private IMetadataRepository[] getRepos() throws CoreException {
785
		URI[] repos = resolveRepositories();
786
		IMetadataRepository[] result = new IMetadataRepository[repos.length];
787
		for (int i = 0; i < repos.length; i++)
788
			result[i] = P2TargetUtils.getRepository(repos[i]);
789
		return result;
790
	}
293
	}
791
294
792
	/**
295
	/**
Lines 794-817 Link Here
794
	 * 
297
	 * 
795
	 * @param toUpdate the set of IU ids in this container to consider updating.  If null
298
	 * @param toUpdate the set of IU ids in this container to consider updating.  If null
796
	 * then update everything
299
	 * then update everything
797
	 * @return a bitmasked int indicating how/if this container changed.  See {@link UpdateTargetJob#DIRTY} and {@link UpdateTargetJob#UPDATED}. 
300
	 * @return a bitmasked int indicating how/if this container changed.  See DIRTY and UPDATED. 
798
	 * @exception CoreException if unable to retrieve IU's
301
	 * @exception CoreException if unable to retrieve IU's
799
	 */
302
	 */
800
	public synchronized int update(Set toUpdate) throws CoreException {
303
	public synchronized int update(Set toUpdate, IProgressMonitor monitor) throws CoreException {
801
		IQueryable source = new CompoundQueryable(getRepos());
304
		SubMonitor progress = SubMonitor.convert(monitor, 100);
305
		IQueryable source = P2TargetUtils.getQueryableMetadata(fRepos, progress.newChild(30));
802
		int dirty = 0;
306
		int dirty = 0;
803
		int updated = 0;
307
		int updated = 0;
308
		SubMonitor loopProgress = progress.newChild(70).setWorkRemaining(fIds.length);
804
		for (int i = 0; i < fIds.length; i++) {
309
		for (int i = 0; i < fIds.length; i++) {
805
			if (!toUpdate.isEmpty() && !toUpdate.contains(fIds[i]))
310
			if (!toUpdate.isEmpty() && !toUpdate.contains(fIds[i]))
806
				continue;
311
				continue;
807
			IQuery query = QueryUtil.createLatestQuery(QueryUtil.createIUQuery(fIds[i]));
312
			IQuery query = QueryUtil.createLatestQuery(QueryUtil.createIUQuery(fIds[i]));
808
			IQueryResult queryResult = source.query(query, null);
313
			IQueryResult queryResult = source.query(query, loopProgress.newChild(1));
809
			Iterator it = queryResult.iterator();
314
			Iterator it = queryResult.iterator();
810
			// bail if the feature is no longer available.
315
			// bail if the feature is no longer available.
811
			if (!it.hasNext())
316
			if (!it.hasNext())
812
				throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, NLS.bind(Messages.IUBundleContainer_1, fIds[i])));
317
				throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, NLS.bind(Messages.IUBundleContainer_1, fIds[i])));
813
			IInstallableUnit iu = (IInstallableUnit) it.next();
318
			IInstallableUnit iu = (IInstallableUnit) it.next();
814
			fUnits[i] = iu;
815
			// if the version is different from the spec (up or down), record the change.
319
			// if the version is different from the spec (up or down), record the change.
816
			if (!iu.getVersion().equals(fVersions[i])) {
320
			if (!iu.getVersion().equals(fVersions[i])) {
817
				updated = UpdateTargetJob.UPDATED;
321
				updated = UpdateTargetJob.UPDATED;
Lines 822-855 Link Here
822
				}
326
				}
823
			}
327
			}
824
		}
328
		}
329
		if (updated == UpdateTargetJob.UPDATED) {
330
			// Things have changed so mark the container as unresolved
331
			clearResolutionStatus();
332
		}
825
		return dirty | updated;
333
		return dirty | updated;
826
	}
334
	}
827
335
828
	/**
336
	protected void clearResolutionStatus() {
829
	 * Checks all other bundle containers in the given target and removes any bundles provided by them from
337
		super.clearResolutionStatus();
830
	 * the map.  This prevents targets containing more than one IUBundleContainer from having duplicate bundles.
338
		fSynchronizer.markDirty();
831
	 * 
832
	 * @param definition target definition to look for other containers in
833
	 * @param bundles collection of bundles arranged by mapping BundleInfo to IResolvedBundle
834
	 */
835
	private void removeDuplicateBundles(ITargetDefinition definition, Map bundles) {
836
		// remove all bundles from previous IU containers (so we don't get duplicates from multi-locations
837
		IBundleContainer[] containers = definition.getBundleContainers();
838
		for (int i = 0; i < containers.length; i++) {
839
			IBundleContainer container = containers[i];
840
			if (container == this) {
841
				break;
842
			}
843
			if (container instanceof IUBundleContainer) {
844
				IUBundleContainer bc = (IUBundleContainer) container;
845
				IResolvedBundle[] included = bc.getBundles();
846
				if (included != null) {
847
					for (int j = 0; j < included.length; j++) {
848
						bundles.remove(included[j].getBundleInfo());
849
					}
850
				}
851
			}
852
		}
853
	}
339
	}
854
340
855
	/**
341
	/**
Lines 857-912 Link Here
857
	 * bundles.  A IResolvedBundle is created for each and a map containing all results
343
	 * bundles.  A IResolvedBundle is created for each and a map containing all results
858
	 * mapping BundleInfo to IResolvedBundle is returned.
344
	 * mapping BundleInfo to IResolvedBundle is returned.
859
	 * <p>
345
	 * <p>
860
	 * If there is an artifact missing for a unit it will either be ignored (not added to the returned map),
346
	 * If there is an artifact missing for a unit it will be ignored (not added to the returned map).
861
	 * or <code>null</code> will be returned depending on the ignoreMissingFiles parameter. 
347
	 * If this container is setup to automatically include source, an corresponding source bundles
348
	 * found in the given profile will also be added as resolved bundles. 
862
	 * </p>
349
	 * </p>
863
	 * @param source A queryable profile or slice that the bundle units will be obtained from
350
	 * @param source the bundle units to be converted
864
	 * @param ignoreMissingFiles if <code>true</code> ius that have missing artifacts will be ignored and not added to the map, if <code>false</code>, <code>null</code> will be returned
351
	 * @param metadata the metadata backing the conversion
865
	 * @return map of BundleInfo to IResolvedBundle or <code>null</code> if a missing file is found and not ignored
352
	 * @param artifacts the underlying artifact repo against which the bundles are validated
353
	 * @return map of BundleInfo to IResolvedBundle
866
	 * @throws CoreException
354
	 * @throws CoreException
867
	 */
355
	 */
868
	private Map generateResolvedBundles(IQueryable source, IFileArtifactRepository repo, boolean ignoreMissingFiles) throws CoreException {
356
	private Map generateResolvedBundles(IQueryable source, IQueryable metadata, IFileArtifactRepository artifacts) throws CoreException {
869
		OSGiBundleQuery query = new OSGiBundleQuery();
357
		OSGiBundleQuery query = new OSGiBundleQuery();
870
		IQueryResult queryResult = source.query(query, null);
358
		IQueryResult queryResult = source.query(query, null);
871
		Map bundles = new LinkedHashMap();
359
		Map bundles = new LinkedHashMap();
872
		for (Iterator iterator = queryResult.iterator(); iterator.hasNext();) {
360
		for (Iterator i = queryResult.iterator(); i.hasNext();) {
873
			IInstallableUnit unit = (IInstallableUnit) iterator.next();
361
			IInstallableUnit unit = (IInstallableUnit) i.next();
874
			Collection artifacts = unit.getArtifacts();
362
			generateBundle(unit, artifacts, bundles);
875
			for (Iterator iterator2 = artifacts.iterator(); iterator2.hasNext();) {
363
			if (getIncludeSource()) {
876
				File file = repo.getArtifactFile((IArtifactKey) iterator2.next());
364
				// bit of a hack using the bundle naming convention for finding source bundles
877
				if (file == null) {
365
				// but this matches what we do when adding source to the profile so...
878
					// Missing file
366
				IQuery sourceQuery = QueryUtil.createIUQuery(unit.getId() + ".source", unit.getVersion()); //$NON-NLS-1$
879
					if (!ignoreMissingFiles) {
367
				IQueryResult result = metadata.query(sourceQuery, null);
880
						if (DEBUG_PROFILE) {
368
				if (!result.isEmpty()) {
881
							System.out.println("Backing file missing for: " + unit.getId()); //$NON-NLS-1$
369
					generateBundle((IInstallableUnit) result.iterator().next(), artifacts, bundles);
882
						}
883
						return null;
884
					}
885
				} else {
886
					IResolvedBundle bundle = generateBundle(file);
887
					if (bundle != null) {
888
						bundles.put(bundle.getBundleInfo(), bundle);
889
					}
890
				}
370
				}
891
			}
371
			}
892
		}
372
		}
893
		return bundles;
373
		return bundles;
894
	}
374
	}
895
375
376
	private void generateBundle(IInstallableUnit unit, IFileArtifactRepository repo, Map bundles) throws CoreException {
377
		Collection artifacts = unit.getArtifacts();
378
		for (Iterator iterator2 = artifacts.iterator(); iterator2.hasNext();) {
379
			File file = repo.getArtifactFile((IArtifactKey) iterator2.next());
380
			if (file != null) {
381
				IResolvedBundle bundle = generateBundle(file);
382
				if (bundle != null) {
383
					bundles.put(bundle.getBundleInfo(), bundle);
384
				}
385
			}
386
		}
387
	}
388
896
	/* (non-Javadoc)
389
	/* (non-Javadoc)
897
	 * @see org.eclipse.pde.internal.core.target.impl.AbstractBundleContainer#isContentEqual(org.eclipse.pde.internal.core.target.impl.AbstractBundleContainer)
390
	 * @see org.eclipse.pde.internal.core.target.impl.AbstractBundleContainer#isContentEqual(org.eclipse.pde.internal.core.target.impl.AbstractBundleContainer)
898
	 */
391
	 */
899
	public boolean isContentEqual(AbstractBundleContainer container) {
392
	public boolean isContentEqual(AbstractBundleContainer container) {
900
		if (container instanceof IUBundleContainer) {
393
		if (container instanceof IUBundleContainer) {
901
			IUBundleContainer iuContainer = (IUBundleContainer) container;
394
			IUBundleContainer iuContainer = (IUBundleContainer) container;
902
			if (iuContainer.getIncludeAllRequired() == getIncludeAllRequired()) {
395
			boolean result = true;
903
				// include all targets only matters if include all required is turned off
396
			result &= iuContainer.getIncludeAllRequired() == getIncludeAllRequired();
904
				if (getIncludeAllRequired() || iuContainer.getIncludeAllEnvironments() == getIncludeAllEnvironments()) {
397
			result &= iuContainer.getIncludeAllEnvironments() == getIncludeAllEnvironments();
905
					return isEqualOrNull(fIds, iuContainer.fIds) && isEqualOrNull(fVersions, iuContainer.fVersions) && isEqualOrNull(fRepos, iuContainer.fRepos);
398
			result &= iuContainer.getIncludeSource() == getIncludeSource();
906
				}
399
			return result && isEqualOrNull(fIds, iuContainer.fIds) && isEqualOrNull(fVersions, iuContainer.fVersions) && isEqualOrNull(fRepos, iuContainer.fRepos);
907
			}
908
			if (fIncludeSource != iuContainer.getIncludeSource())
909
				return false;
910
		}
400
		}
911
		return false;
401
		return false;
912
	}
402
	}
Lines 947-1087 Link Here
947
	}
437
	}
948
438
949
	/**
439
	/**
950
	 * Returns the repositories to consider when resolving IU's (will return default set of
440
	 * Removes an installable unit from this container.  The container will no longer be resolved.
951
	 * repositories if current repository settings are <code>null</code>).
952
	 *  
953
	 * @return URI's of repositories to use when resolving bundles
954
	 * @exception CoreException
955
	 */
956
	private URI[] resolveRepositories() throws CoreException {
957
		if (fRepos == null) {
958
			IMetadataRepositoryManager manager = P2TargetUtils.getRepoManager();
959
			return manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
960
		}
961
		return fRepos;
962
	}
963
964
	/**
965
	 * Returns the artifact repositories to consider when getting artifacts.  Returns a default set of
966
	 * repositories if current repository settings are <code>null</code>).
967
	 *  
441
	 *  
968
	 * @return URI's of repositories to use when getting artifacts
442
	 * @param unit unit to remove from the list of root IUs
969
	 * @exception CoreException
970
	 */
971
	private URI[] resolveArtifactRepositories() throws CoreException {
972
		URI[] repositories = fRepos;
973
		if (fRepos == null) {
974
			IArtifactRepositoryManager manager = P2TargetUtils.getArtifactRepositoryManager();
975
			repositories = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
976
		}
977
		if (!useAdditionalLocalArtifacts())
978
			return repositories;
979
		Set additionalRepos = new HashSet(Arrays.asList(repositories));
980
		findProfileRepos(additionalRepos);
981
		findWorkspaceRepos(additionalRepos);
982
		return (URI[]) additionalRepos.toArray(new URI[additionalRepos.size()]);
983
	}
984
985
	/**
986
	 * @return whether to use local artifact repositories when provisioning the target
987
	 */
988
	private boolean useAdditionalLocalArtifacts() {
989
		// TODO consider using a preference here or another strategy if users are able to spec 
990
		// what local repos are to be considered.
991
		return true;
992
	}
993
994
	/** 
995
	 * Add the artifact repos from the PDE target bundle pools from all known repos.  For example, the list 
996
	 * of "recent workspaces" maintained by the IDE is a good source.
997
	 * 
998
	 * @param additionalRepos the set to which additional repos are added.
999
	 */
1000
	private void findWorkspaceRepos(Set additionalRepos) {
1001
		IPreferencesService prefs = P2TargetUtils.getPreferences();
1002
		if (prefs == null)
1003
			return;
1004
		String recent = prefs.getString("org.eclipse.ui.ide", "RECENT_WORKSPACES", null, null); //$NON-NLS-1$ //$NON-NLS-2$
1005
		if (recent == null)
1006
			return;
1007
		String[] recents = recent.split("\n"); //$NON-NLS-1$
1008
		for (int i = 0; i < recents.length; i++) {
1009
			String bundlePool = recents[i] + "/.metadata/.plugins/org.eclipse.pde.core/.bundle_pool"; //$NON-NLS-1$
1010
			if (new File(bundlePool).exists()) {
1011
				URI uri;
1012
				try {
1013
					uri = new URI("file", bundlePool, null); //$NON-NLS-1$
1014
					additionalRepos.add(uri);
1015
				} catch (URISyntaxException e) {
1016
					// should never happen
1017
				}
1018
			}
1019
		}
1020
	}
1021
1022
	/** 
1023
	 * Look through the current p2 profile (_SELF_) and add the artifact repos that make up its
1024
	 * bundle pool, dropins location, ...  This helps in the cases that you are targeting stuff that 
1025
	 * makes up your current IDE.
1026
	 * 
1027
	 * @param additionalRepos the set to which additional repos are added.
1028
	 */
443
	 */
1029
	private void findProfileRepos(Set additionalRepos) {
444
	public synchronized void removeInstallableUnit(IInstallableUnit unit) {
1030
		try {
445
		List newIds = new ArrayList(fIds.length);
1031
			// NOTE: be sure to use the global p2 agent here as we are looking for SELF.
446
		List newVersions = new ArrayList(fIds.length);
1032
			IProfileRegistry profileRegistry = (IProfileRegistry) P2TargetUtils.getGlobalAgent().getService(IProfileRegistry.SERVICE_NAME);
447
		for (int i = 0; i < fIds.length; i++) {
1033
			if (profileRegistry == null)
448
			if (!fIds[i].equals(unit.getId()) || !fVersions[i].equals(unit.getVersion())) {
1034
				return;
449
				newIds.add(fIds[i]);
1035
			IProfile self = profileRegistry.getProfile(IProfileRegistry.SELF);
450
				newVersions.add(fVersions[i]);
1036
			if (self == null)
1037
				return;
1038
1039
			IAgentLocation location = (IAgentLocation) P2TargetUtils.getGlobalAgent().getService(IAgentLocation.SERVICE_NAME);
1040
			URI dataArea = location.getDataArea("org.eclipse.equinox.p2.engine"); //$NON-NLS-1$
1041
			dataArea = URIUtil.append(dataArea, "profileRegistry/" + self.getProfileId() + ".profile"); //$NON-NLS-1$//$NON-NLS-2$
1042
			ProfileMetadataRepository profileRepo = new ProfileMetadataRepository(P2TargetUtils.getGlobalAgent(), dataArea, null);
1043
			Collection repos = profileRepo.getReferences();
1044
			for (Iterator i = repos.iterator(); i.hasNext();) {
1045
				Object element = i.next();
1046
				if (element instanceof IRepositoryReference) {
1047
					IRepositoryReference reference = (IRepositoryReference) element;
1048
					if (reference.getType() == IRepository.TYPE_ARTIFACT && reference.getLocation() != null)
1049
						additionalRepos.add(reference.getLocation());
1050
				}
1051
			}
451
			}
1052
		} catch (CoreException e) {
1053
			// if there is a problem, move on.  Could log something here 
1054
			return;
1055
		}
452
		}
1056
	}
453
		fIds = (String[]) newIds.toArray(new String[newIds.size()]);
454
		fVersions = (Version[]) newVersions.toArray(new Version[newVersions.size()]);
1057
455
1058
	/**
456
		// Need to mark the container as unresolved
1059
	 * Sets whether all required units must be available to resolve this container.  When <code>true</code>
457
		clearResolutionStatus();
1060
	 * the resolve operation will use the planner to determine the complete set of IUs required to
1061
	 * make the selected IUs runnable.  If any dependencies are missing, the resolve operation will return an
1062
	 * error explaining what problems exist.  When <code>false</code> the resolve operation will use the slicer
1063
	 * to determine what units to include.  Any required units that are not available in the repositories will
1064
	 * be ignored.
1065
	 * <p>
1066
	 * Since there is only one profile per target and the planner and slicer resolve methods are incompatible
1067
	 * it is highly recommended that the parent target be passed to this method so all other IUBundleContainers
1068
	 * in the target can be updated with the new setting. 
1069
	 * </p>
1070
	 * @param include whether all required units must be available to resolve this container
1071
	 * @param definition parent target, used to update other IUBundleContainers with this setting, can be <code>null</code>
1072
	 */
1073
	public void setIncludeAllRequired(boolean include, ITargetDefinition definition) {
1074
		fIncludeAllRequired = include;
1075
		if (definition != null) {
1076
			IBundleContainer[] containers = definition.getBundleContainers();
1077
			if (containers != null) {
1078
				for (int i = 0; i < containers.length; i++) {
1079
					if (containers[i] instanceof IUBundleContainer && containers[i] != this) {
1080
						((IUBundleContainer) containers[i]).setIncludeAllRequired(include, null);
1081
					}
1082
				}
1083
			}
1084
		}
1085
	}
458
	}
1086
459
1087
	/**
460
	/**
Lines 1095-1129 Link Here
1095
	 * @return whether all required units must be available to resolve this container
468
	 * @return whether all required units must be available to resolve this container
1096
	 */
469
	 */
1097
	public boolean getIncludeAllRequired() {
470
	public boolean getIncludeAllRequired() {
1098
		return fIncludeAllRequired;
471
		// if this container has not been associated with a container, return its own value
1099
	}
472
		if (fSynchronizer == null)
1100
473
			return (fFlags & INCLUDE_REQUIRED) == INCLUDE_REQUIRED;
1101
	/**
474
		return fSynchronizer.getIncludeAllRequired();
1102
	 * Sets whether all environment (platform) specific installable units should
1103
	 * be included in this container when it is resolved.  This feature is not supported
1104
	 * by the planner so will only have an effect if the include all required setting
1105
	 * is turned off ({@link #getIncludeAllRequired()}).
1106
	 * <p>
1107
	 * There is only one profile per target and this setting can only be set for the
1108
	 * entire target definition.  It is highly recommended that the parent target be passed
1109
	 * to this method so all other IUBundleContainers in the target can be updated with the 
1110
	 * new setting. 
1111
	 * </p>
1112
	 * @param include whether environment specific units should be included
1113
	 * @param definition parent target, used to update other IUBundleContainers with this setting, can be <code>null</code>
1114
	 */
1115
	public void setIncludeAllEnvironments(boolean include, ITargetDefinition definition) {
1116
		fIncludeMultipleEnvironments = include;
1117
		if (definition != null) {
1118
			IBundleContainer[] containers = definition.getBundleContainers();
1119
			if (containers != null) {
1120
				for (int i = 0; i < containers.length; i++) {
1121
					if (containers[i] instanceof IUBundleContainer && containers[i] != this) {
1122
						((IUBundleContainer) containers[i]).setIncludeAllEnvironments(include, null);
1123
					}
1124
				}
1125
			}
1126
		}
1127
	}
475
	}
1128
476
1129
	/**
477
	/**
Lines 1135-1151 Link Here
1135
	 * @return whether environment specific units should be included
483
	 * @return whether environment specific units should be included
1136
	 */
484
	 */
1137
	public boolean getIncludeAllEnvironments() {
485
	public boolean getIncludeAllEnvironments() {
1138
		return fIncludeMultipleEnvironments;
486
		// if this container has not been associated with a container, return its own value
1139
	}
487
		if (fSynchronizer == null)
1140
488
			return (fFlags & INCLUDE_ALL_ENVIRONMENTS) == INCLUDE_ALL_ENVIRONMENTS;
1141
	/**
489
		return fSynchronizer.getIncludeAllEnvironments();
1142
	 * Set whether or not the source bundles corresponding to any binary bundles should
1143
	 * be automatically included in the target.
1144
	 * 
1145
	 * @param value whether or not to include source
1146
	 */
1147
	public void setIncludeSource(boolean value) {
1148
		fIncludeSource = value;
1149
	}
490
	}
1150
491
1151
	/**
492
	/**
Lines 1155-1184 Link Here
1155
	 * @return whether or not source is included automatically
496
	 * @return whether or not source is included automatically
1156
	 */
497
	 */
1157
	public boolean getIncludeSource() {
498
	public boolean getIncludeSource() {
1158
		return fIncludeSource;
499
		// if this container has not been associated with a container, return its own value
500
		if (fSynchronizer == null)
501
			return (fFlags & INCLUDE_SOURCE) == INCLUDE_SOURCE;
502
		return fSynchronizer.getIncludeSource();
1159
	}
503
	}
1160
504
1161
	/**
505
	/**
1162
	 * Removes an installable unit from this container.  The container will no longer be resolved.
506
	 * Returns the installable units defined by this container
1163
	 *  
507
	 * 
1164
	 * @param unit unit to remove from the list of root IUs
508
	 * @return the discovered IUs
509
	 * @exception CoreException if unable to retrieve IU's
1165
	 */
510
	 */
1166
	public void removeInstallableUnit(IInstallableUnit unit) {
511
	public IInstallableUnit[] getInstallableUnits() throws CoreException {
1167
		List newUnits = new ArrayList(fUnits.length);
512
		if (fUnits == null)
1168
		for (int i = 0; i < fUnits.length; i++) {
513
			return new IInstallableUnit[0];
1169
			if (!fUnits[i].equals(unit)) {
514
		return fUnits;
1170
				newUnits.add(fUnits[i]);
1171
			}
1172
		}
1173
		fUnits = (IInstallableUnit[]) newUnits.toArray(new IInstallableUnit[newUnits.size()]);
1174
		fIds = new String[fUnits.length];
1175
		fVersions = new Version[fUnits.length];
1176
		for (int i = 0; i < fUnits.length; i++) {
1177
			fIds[i] = fUnits[i].getId();
1178
			fVersions[i] = fUnits[i].getVersion();
1179
		}
1180
		// Need to mark the container as unresolved
1181
		clearResolutionStatus();
1182
	}
515
	}
1183
516
1184
	/**
517
	/**
Lines 1199-1202 Link Here
1199
		return fVersions;
532
		return fVersions;
1200
	}
533
	}
1201
534
535
	/**
536
	 * Return the synchronizer for this container.  If there isn't one and a target definition is 
537
	 * supplied, then get/create the one used by the target and the other containers.
538
	 */
539
	P2TargetUtils getSynchronizer(ITargetDefinition definition) {
540
		if (fSynchronizer != null) {
541
			return fSynchronizer;
542
		}
543
		if (definition == null)
544
			return null;
545
		return fSynchronizer = P2TargetUtils.getSynchronizer(definition);
546
	}
547
548
	/**
549
	 * Callback method used by the synchronizer to associate containers with 
550
	 * synchronizers.
551
	 */
552
	void setSynchronizer(P2TargetUtils value) {
553
		fSynchronizer = value;
554
	}
555
556
	/**
557
	 * Associate this container with the given target.  The include settings for this container
558
	 * override the settings for all other IU containers in the target.  Last one wins.
559
	 */
560
	protected void associateWithTarget(ITargetDefinition target) {
561
		super.associateWithTarget(target);
562
		fSynchronizer = getSynchronizer(target);
563
		fSynchronizer.setIncludeAllRequired((fFlags & INCLUDE_REQUIRED) == INCLUDE_REQUIRED);
564
		fSynchronizer.setIncludeAllEnvironments((fFlags & INCLUDE_ALL_ENVIRONMENTS) == INCLUDE_ALL_ENVIRONMENTS);
565
		fSynchronizer.setIncludeSource((fFlags & INCLUDE_SOURCE) == INCLUDE_SOURCE);
566
	}
1202
}
567
}
(-)src/org/eclipse/pde/internal/core/target/Messages.java (+1 lines)
Lines 34-39 Link Here
34
	public static String IUBundleContainer_0;
34
	public static String IUBundleContainer_0;
35
	public static String IUBundleContainer_1;
35
	public static String IUBundleContainer_1;
36
	public static String IUBundleContainer_10;
36
	public static String IUBundleContainer_10;
37
	public static String IUBundleContainer_11;
37
	public static String IUBundleContainer_2;
38
	public static String IUBundleContainer_2;
38
	public static String IUBundleContainer_3;
39
	public static String IUBundleContainer_3;
39
	public static String IUBundleContainer_4;
40
	public static String IUBundleContainer_4;
(-)src/org/eclipse/pde/internal/core/target/Messages.properties (-2 / +3 lines)
Lines 25-38 Link Here
25
FeatureBundleContainer_5=Plug-ins directory does not exist for feature {0}
25
FeatureBundleContainer_5=Plug-ins directory does not exist for feature {0}
26
IUBundleContainer_0=Provisioning target
26
IUBundleContainer_0=Provisioning target
27
IUBundleContainer_1=Unable to locate installable unit {0}
27
IUBundleContainer_1=Unable to locate installable unit {0}
28
IUBundleContainer_10=Provisioning Agent service not found
28
IUBundleContainer_10=Provisioning Agent Location service not found
29
IUBundleContainer_11=Global Provisioning Agent service not found
29
IUBundleContainer_2=Metadata repository service not found
30
IUBundleContainer_2=Metadata repository service not found
30
IUBundleContainer_3=Artifact respository service not found
31
IUBundleContainer_3=Artifact respository service not found
31
IUBundleContainer_4=Provisioning engine not found
32
IUBundleContainer_4=Provisioning engine not found
32
IUBundleContainer_5=Provisioning planner not found
33
IUBundleContainer_5=Provisioning planner not found
33
IUBundleContainer_6=Target provisioning skipped install plan
34
IUBundleContainer_6=Target provisioning skipped install plan
34
IUBundleContainer_7=Provisioning agent not found
35
IUBundleContainer_7=Provisioning agent not found
35
IUBundleContainer_8=Profile registry service not found
36
IUBundleContainer_8=Profile Registry service not found
36
IUBundleContainer_9=Garbage Collector service not found
37
IUBundleContainer_9=Garbage Collector service not found
37
IUBundleContainer_LoadingFromProfileJob=Loading target information from profile
38
IUBundleContainer_LoadingFromProfileJob=Loading target information from profile
38
IUBundleContainer_NoBundlePool=No location for downloaded bundles could be found.
39
IUBundleContainer_NoBundlePool=No location for downloaded bundles could be found.
(-)src/org/eclipse/pde/internal/core/target/P2TargetUtils.java (-146 / +996 lines)
Lines 12-38 Link Here
12
12
13
import java.io.File;
13
import java.io.File;
14
import java.net.URI;
14
import java.net.URI;
15
import java.net.URISyntaxException;
15
import java.util.*;
16
import java.util.*;
16
import org.eclipse.core.runtime.*;
17
import org.eclipse.core.runtime.*;
17
import org.eclipse.core.runtime.preferences.IPreferencesService;
18
import org.eclipse.core.runtime.preferences.IPreferencesService;
19
import org.eclipse.equinox.internal.p2.director.PermissiveSlicer;
20
import org.eclipse.equinox.internal.p2.engine.*;
21
import org.eclipse.equinox.internal.p2.engine.phases.*;
18
import org.eclipse.equinox.internal.p2.garbagecollector.GarbageCollector;
22
import org.eclipse.equinox.internal.p2.garbagecollector.GarbageCollector;
19
import org.eclipse.equinox.p2.core.*;
23
import org.eclipse.equinox.p2.core.*;
20
import org.eclipse.equinox.p2.engine.*;
24
import org.eclipse.equinox.p2.engine.*;
21
import org.eclipse.equinox.p2.engine.query.IUProfilePropertyQuery;
25
import org.eclipse.equinox.p2.engine.query.IUProfilePropertyQuery;
22
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
26
import org.eclipse.equinox.p2.engine.spi.ProvisioningAction;
27
import org.eclipse.equinox.p2.metadata.*;
28
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
23
import org.eclipse.equinox.p2.metadata.Version;
29
import org.eclipse.equinox.p2.metadata.Version;
24
import org.eclipse.equinox.p2.planner.IPlanner;
30
import org.eclipse.equinox.p2.planner.IPlanner;
25
import org.eclipse.equinox.p2.query.IQueryResult;
31
import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
26
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
32
import org.eclipse.equinox.p2.query.*;
27
import org.eclipse.equinox.p2.repository.artifact.IFileArtifactRepository;
33
import org.eclipse.equinox.p2.repository.*;
28
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
34
import org.eclipse.equinox.p2.repository.artifact.*;
29
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
35
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
36
import org.eclipse.osgi.util.NLS;
30
import org.eclipse.pde.internal.core.PDECore;
37
import org.eclipse.pde.internal.core.PDECore;
31
import org.eclipse.pde.internal.core.target.provisional.*;
38
import org.eclipse.pde.internal.core.target.provisional.*;
32
import org.osgi.framework.*;
39
import org.osgi.framework.*;
33
40
34
public class P2TargetUtils {
41
public class P2TargetUtils {
35
42
43
	private static final String SOURCE_IU_ID = "org.eclipse.pde.core.target.source.bundles"; //$NON-NLS-1$
44
36
	/**
45
	/**
37
	 * URI to the local directory where the p2 agent keeps its information.
46
	 * URI to the local directory where the p2 agent keeps its information.
38
	 */
47
	 */
Lines 81-86 Link Here
81
	static final String PROP_ALL_ENVIRONMENTS = PDECore.PLUGIN_ID + ".all_environments"; //$NON-NLS-1$	
90
	static final String PROP_ALL_ENVIRONMENTS = PDECore.PLUGIN_ID + ".all_environments"; //$NON-NLS-1$	
82
91
83
	/**
92
	/**
93
	 * Profile property that keeps track of the target sequence number
94
	 */
95
	static final String PROP_SEQUENCE_NUMBER = PDECore.PLUGIN_ID + ".sequence"; //$NON-NLS-1$	
96
97
	/**
98
	 * Profile property that tracks whether or not source to be auto-included
99
	 */
100
	static final String PROP_AUTO_INCLUDE_SOURCE = PDECore.PLUGIN_ID + ".autoIncludeSource"; //$NON-NLS-1$	
101
102
	/** 
103
	 * The profile to be synchronized
104
	 */
105
	private IProfile fProfile;
106
107
	/**
108
	 * The target to be synchronized.
109
	 */
110
	private ITargetDefinition fTarget;
111
112
	/**
113
	 * Whether this container must have all required IUs of the selected IUs available and included
114
	 * in the target to resolve successfully.  If this option is true, the planner will be used to resolve
115
	 * otherwise the slicer is used.  The planner can describe any missing requirements as errors.
116
	 * <p>
117
	 * <code>true</code> by default
118
	 * </p>
119
	 */
120
	private boolean fIncludeAllRequired = true;
121
122
	/**
123
	 * Whether this container should download and include environment (platform) specific units for all
124
	 * available platforms (vs only the current target definition's environment settings).  Only supported 
125
	 * by the slicer so {@link fIncludeAllRequired} must be turned off for this setting to be used.
126
	 * <p>
127
	 * <code>false</code> by default
128
	 * </p>
129
	 */
130
	private boolean fIncludeMultipleEnvironments = false;
131
132
	/**
133
	 * Whether this container should download and include source bundles for the selected units if the associated
134
	 * source is available in the repository.
135
	 * <p>
136
	 * <code>false</code>by default
137
	 */
138
	private boolean fIncludeSource = false;
139
140
	/**
141
	 * Whether or not this synchronizer is dirty by means other than target tweaks etc.
142
	 */
143
	private boolean fDirty = false;
144
145
	public P2TargetUtils(ITargetDefinition target) {
146
		fTarget = target;
147
	}
148
149
	/**
84
	 * Deletes any profiles associated with target definitions that no longer exist
150
	 * Deletes any profiles associated with target definitions that no longer exist
85
	 * and returns a list of profile identifiers that were deleted.
151
	 * and returns a list of profile identifiers that were deleted.
86
	 */
152
	 */
Lines 93-100 Link Here
93
			for (int i = 0; i < profiles.length; i++) {
159
			for (int i = 0; i < profiles.length; i++) {
94
				IProfile profile = profiles[i];
160
				IProfile profile = profiles[i];
95
				String id = profile.getProfileId();
161
				String id = profile.getProfileId();
96
				if (id.startsWith(P2TargetUtils.PROFILE_ID_PREFIX)) {
162
				if (id.startsWith(PROFILE_ID_PREFIX)) {
97
					String memento = id.substring(P2TargetUtils.PROFILE_ID_PREFIX.length());
163
					String memento = id.substring(PROFILE_ID_PREFIX.length());
98
					ITargetHandle handle = tps.getTarget(memento);
164
					ITargetHandle handle = tps.getTarget(memento);
99
					if (!handle.exists()) {
165
					if (!handle.exists()) {
100
						deleteProfile(handle);
166
						deleteProfile(handle);
Lines 154-160 Link Here
154
		try {
220
		try {
155
			IProfile[] profiles = getProfileRegistry().getProfiles();
221
			IProfile[] profiles = getProfileRegistry().getProfiles();
156
			for (int i = 0; i < profiles.length; i++) {
222
			for (int i = 0; i < profiles.length; i++) {
157
				if (profiles[i].getProfileId().startsWith(P2TargetUtils.PROFILE_ID_PREFIX)) {
223
				if (profiles[i].getProfileId().startsWith(PROFILE_ID_PREFIX)) {
158
					getGarbageCollector().runGC(profiles[i]);
224
					getGarbageCollector().runGC(profiles[i]);
159
				}
225
				}
160
			}
226
			}
Lines 169-175 Link Here
169
	 * 
235
	 * 
170
	 * @return environment properties
236
	 * @return environment properties
171
	 */
237
	 */
172
	private static String generateEnvironmentProperties(ITargetDefinition target) {
238
	private String generateEnvironmentProperties(ITargetDefinition target) {
173
		// TODO: are there constants for these keys?
239
		// TODO: are there constants for these keys?
174
		StringBuffer env = new StringBuffer();
240
		StringBuffer env = new StringBuffer();
175
		String ws = target.getWS();
241
		String ws = target.getWS();
Lines 200-206 Link Here
200
	 * 
266
	 * 
201
	 * @return NL profile property
267
	 * @return NL profile property
202
	 */
268
	 */
203
	private static String generateNLProperty(ITargetDefinition target) {
269
	private String generateNLProperty(ITargetDefinition target) {
204
		String nl = target.getNL();
270
		String nl = target.getNL();
205
		if (nl == null) {
271
		if (nl == null) {
206
			nl = Platform.getNL();
272
			nl = Platform.getNL();
Lines 246-252 Link Here
246
	public static IProvisioningAgent getGlobalAgent() throws CoreException {
312
	public static IProvisioningAgent getGlobalAgent() throws CoreException {
247
		IProvisioningAgent agent = (IProvisioningAgent) PDECore.getDefault().acquireService(IProvisioningAgent.SERVICE_NAME);
313
		IProvisioningAgent agent = (IProvisioningAgent) PDECore.getDefault().acquireService(IProvisioningAgent.SERVICE_NAME);
248
		if (agent == null)
314
		if (agent == null)
249
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_10));
315
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_11));
250
		return agent;
316
		return agent;
251
	}
317
	}
252
318
Lines 278-299 Link Here
278
	}
344
	}
279
345
280
	/**
346
	/**
281
	 * Returns the local bundle pool (repository) where bundles are stored for the
347
	 * Returns the local bundle pool (repository) where bundles are stored
282
	 * given profile.
283
	 * 
348
	 * 
284
	 * @param profile profile bundles are stored
285
	 * @return local file artifact repository
349
	 * @return local file artifact repository
286
	 * @throws CoreException
350
	 * @throws CoreException
287
	 */
351
	 */
288
	public static IFileArtifactRepository getBundlePool(IProfile profile) throws CoreException {
352
	public static IFileArtifactRepository getBundlePool() throws CoreException {
289
		String path = profile.getProperty(IProfile.PROP_CACHE);
353
		URI uri = BUNDLE_POOL.toFile().toURI();
290
		if (path == null) {
291
			// We should always be setting the bundle pool, so if the bundle pool location is missing there isn't much we can do 
292
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_NoBundlePool));
293
		}
294
		URI uri = new File(path).toURI();
295
		IArtifactRepositoryManager manager = getArtifactRepositoryManager();
354
		IArtifactRepositoryManager manager = getArtifactRepositoryManager();
296
		return (IFileArtifactRepository) manager.loadRepository(uri, null);
355
		try {
356
			if (manager.contains(uri))
357
				return (IFileArtifactRepository) manager.loadRepository(uri, null);
358
		} catch (CoreException e) {
359
			// could not load or there wasn't one, fall through to create 
360
		}
361
		String repoName = "PDE Target Bundle Pool"; //$NON-NLS-1$
362
		IArtifactRepository result = manager.createRepository(uri, repoName, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
363
		return (IFileArtifactRepository) result;
297
	}
364
	}
298
365
299
	/**
366
	/**
Lines 331-337 Link Here
331
	 * @throws CoreException if none
398
	 * @throws CoreException if none
332
	 */
399
	 */
333
	public static IPlanner getPlanner() throws CoreException {
400
	public static IPlanner getPlanner() throws CoreException {
334
		IPlanner planner = (IPlanner) P2TargetUtils.getAgent().getService(IPlanner.class.getName());
401
		IPlanner planner = (IPlanner) getAgent().getService(IPlanner.class.getName());
335
		if (planner == null) {
402
		if (planner == null) {
336
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_5));
403
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_5));
337
		}
404
		}
Lines 348-454 Link Here
348
	}
415
	}
349
416
350
	/**
417
	/**
351
	 * Returns the profile for the this target handle, creating one if required.
418
	 * Returns whether the contents of the profile matches the expected contents of the target definition
352
	 * 
419
	 * 
353
	 * @return profile
420
	 * @return whether or not the profile and target definitions match
354
	 * @throws CoreException in unable to retrieve profile
421
	 * @throws CoreException in unable to retrieve profile
355
	 */
422
	 */
356
	public static IProfile getProfile(ITargetDefinition target) throws CoreException {
423
	private boolean checkProfile() throws CoreException {
357
		IProfileRegistry registry = getProfileRegistry();
424
		// make sure we have a profile to validate
358
		if (registry == null) {
425
		if (fProfile == null) {
359
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.AbstractTargetHandle_0));
426
			return false;
427
		}
428
429
		if (fDirty)
430
			return false;
431
		// check that the target and profiles are in sync. If they are then life is good.
432
		// If they are not equal, there is still a chance that everything is ok.
433
		String profileNumber = fProfile.getProperty(PROP_SEQUENCE_NUMBER);
434
		if (Integer.toString(fTarget.currentSequenceNumber()).equals(profileNumber)) {
435
			return true;
436
		}
437
438
		// check if all environments setting is the same
439
		boolean all = false;
440
		String value = fProfile.getProperty(PROP_ALL_ENVIRONMENTS);
441
		if (value != null) {
442
			all = Boolean.valueOf(value).booleanValue();
443
			if (!Boolean.toString(getIncludeAllEnvironments()).equals(value)) {
444
				return false;
445
			}
360
		}
446
		}
361
		AbstractTargetHandle handle = ((AbstractTargetHandle) target.getHandle());
447
362
		String id = P2TargetUtils.getProfileId(handle);
448
		// ensure environment & NL settings are still the same (else we need a new profile)
363
		IProfile profile = registry.getProfile(id);
449
		String property = null;
364
		if (profile != null) {
450
		if (!all) {
365
			boolean recreate = false;
451
			property = generateEnvironmentProperties(fTarget);
366
			// check if all environments setting is the same
452
			value = fProfile.getProperty(IProfile.PROP_ENVIRONMENTS);
367
			boolean all = false;
453
			if (!property.equals(value)) {
368
			String value = profile.getProperty(P2TargetUtils.PROP_ALL_ENVIRONMENTS);
454
				return false;
369
			if (value != null) {
455
			}
370
				all = Boolean.valueOf(value).booleanValue();
456
		}
371
				if (!Boolean.toString(isAllEnvironments(target)).equals(value)) {
457
		property = generateNLProperty(fTarget);
372
					recreate = true;
458
		value = fProfile.getProperty(IProfile.PROP_NL);
373
				}
459
		if (!property.equals(value)) {
374
			}
460
			return false;
375
			// ensure environment & NL settings are still the same (else we need a new profile)
461
		}
376
			String property = null;
462
377
			if (!recreate && !all) {
463
		// check provisioning mode: slice versus plan
378
				property = generateEnvironmentProperties(target);
464
		if (!getProvisionMode(fTarget).equals(fProfile.getProperty(PROP_PROVISION_MODE))) {
379
				value = profile.getProperty(IProfile.PROP_ENVIRONMENTS);
465
			return false;
380
				if (!property.equals(value)) {
466
		}
381
					recreate = true;
467
382
				}
468
		// check that the include source flag matches what the profile represents
383
			}
469
		if (getIncludeSource() != Boolean.valueOf(fProfile.getProperty(PROP_AUTO_INCLUDE_SOURCE)).booleanValue()) {
384
			// check provisioning mode: slice versus plan
470
			return false;
385
			String mode = getProvisionMode(target);
471
		}
386
			if (mode != null) {
472
387
				value = profile.getProperty(P2TargetUtils.PROP_PROVISION_MODE);
473
		// check top level IU's. If any have been removed from the containers that are
388
				if (!mode.equals(value)) {
474
		// still in the profile, we need to recreate (rather than uninstall)
389
					recreate = true;
475
		IUProfilePropertyQuery propertyQuery = new IUProfilePropertyQuery(PROP_INSTALLED_IU, Boolean.toString(true));
476
		IQueryResult queryResult = fProfile.query(propertyQuery, null);
477
		Iterator iterator = queryResult.iterator();
478
		Set installedIUs = new HashSet();
479
		while (iterator.hasNext()) {
480
			IInstallableUnit unit = (IInstallableUnit) iterator.next();
481
			installedIUs.add(new NameVersionDescriptor(unit.getId(), unit.getVersion().toString()));
482
		}
483
		IBundleContainer[] containers = fTarget.getBundleContainers();
484
		if (containers == null) {
485
			return installedIUs.isEmpty();
486
		}
487
		for (int i = 0; i < containers.length; i++) {
488
			if (containers[i] instanceof IUBundleContainer) {
489
				IUBundleContainer bc = (IUBundleContainer) containers[i];
490
				String[] ids = bc.getIds();
491
				Version[] versions = bc.getVersions();
492
				for (int j = 0; j < versions.length; j++) {
493
					// if there is something in a container but not in the profile, recreate
494
					if (!installedIUs.remove(new NameVersionDescriptor(ids[j], versions[j].toString()))) {
495
						return false;
496
					}
390
				}
497
				}
391
			}
498
			}
499
		}
500
		if (!installedIUs.isEmpty()) {
501
			return false;
502
		}
392
503
393
			if (!recreate) {
504
		// Phew! seems like the profile checks out.  
394
				property = generateNLProperty(target);
505
		return true;
395
				value = profile.getProperty(IProfile.PROP_NL);
506
	}
396
				if (!property.equals(value)) {
507
397
					recreate = true;
508
	/**
398
				}
509
	 * Sets whether all required units must be available to resolve this container.  When <code>true</code>
399
			}
510
	 * the resolve operation will use the planner to determine the complete set of IUs required to
400
			if (!recreate) {
511
	 * make the selected IUs runnable.  If any dependencies are missing, the resolve operation will return an
401
				// check top level IU's. If any have been removed from the containers that are
512
	 * error explaining what problems exist.  When <code>false</code> the resolve operation will use the slicer
402
				// still in the profile, we need to recreate (rather than uninstall)
513
	 * to determine what units to include.  Any required units that are not available in the repositories will
403
				IUProfilePropertyQuery propertyQuery = new IUProfilePropertyQuery(P2TargetUtils.PROP_INSTALLED_IU, Boolean.toString(true));
514
	 * be ignored.
404
				IQueryResult queryResult = profile.query(propertyQuery, null);
515
	 * <p>
405
				Iterator iterator = queryResult.iterator();
516
	 * Since there is only one profile per target and the planner and slicer resolve methods are incompatible.
406
				if (iterator.hasNext()) {
517
	 * </p>
407
					Set installedIUs = new HashSet();
518
	 * @param value whether all required units must be available to resolve this container
408
					while (iterator.hasNext()) {
519
	 */
409
						IInstallableUnit unit = (IInstallableUnit) iterator.next();
520
	public void setIncludeAllRequired(boolean value) {
410
						installedIUs.add(new NameVersionDescriptor(unit.getId(), unit.getVersion().toString()));
521
		fIncludeAllRequired = value;
411
					}
522
	}
412
					IBundleContainer[] containers = target.getBundleContainers();
523
413
					if (containers != null) {
524
	/**
414
						for (int i = 0; i < containers.length; i++) {
525
	 * Returns whether all required units must be available to resolve this container.  When <code>true</code>
415
							if (containers[i] instanceof IUBundleContainer) {
526
	 * the resolve operation will use the planner to determine the complete set of IUs required to
416
								IUBundleContainer bc = (IUBundleContainer) containers[i];
527
	 * make the selected IUs runnable.  If any dependencies are missing, the resolve operation will return an
417
								String[] ids = bc.getIds();
528
	 * error explaining what problems exist.  When <code>false</code> the resolve operation will use the slicer
418
								Version[] versions = bc.getVersions();
529
	 * to determine what units to include.  Any required units that are not available in the repositories will
419
								for (int j = 0; j < versions.length; j++) {
530
	 * be ignored.
420
									installedIUs.remove(new NameVersionDescriptor(ids[j], versions[j].toString()));
531
	 *  
421
								}
532
	 * @return whether all required units must be available to resolve this container
422
							}
533
	 */
423
						}
534
	public boolean getIncludeAllRequired() {
424
					}
535
		return fIncludeAllRequired;
425
					if (!installedIUs.isEmpty()) {
536
	}
426
						recreate = true;
537
427
					}
538
	/**
539
	 * Sets whether all environment (platform) specific installable units should
540
	 * be included in this container when it is resolved.  This feature is not supported
541
	 * by the planner so will only have an effect if the include all required setting
542
	 * is turned off ({@link #getIncludeAllRequired()}).
543
	 * <p>
544
	 * There is only one profile per target and this setting can only be set for the
545
	 * entire target definition.  
546
	 * </p>
547
	 * @param value whether environment specific units should be included
548
	 */
549
	public void setIncludeAllEnvironments(boolean value) {
550
		fIncludeMultipleEnvironments = value;
551
	}
552
553
	/**
554
	 * Returns whether all environment (platform) specific installable units should
555
	 * be included in this container when it is resolved.  This feature is not supported
556
	 * by the planner so will only have an effect if the include all required setting
557
	 * is turned off ({@link #getIncludeAllRequired()}).
558
	 * 
559
	 * @return whether environment specific units should be included
560
	 */
561
	public boolean getIncludeAllEnvironments() {
562
		return fIncludeMultipleEnvironments;
563
	}
564
565
	/**
566
	 * Set whether or not the source bundles corresponding to any binary bundles should
567
	 * be automatically included in the target.
568
	 * 
569
	 * @param value whether or not to include source
570
	 */
571
	public void setIncludeSource(boolean value) {
572
		fIncludeSource = value;
573
	}
574
575
	/**
576
	 * Returns whether or not source bundles corresponding to selected binary bundles 
577
	 * are automatically included in the target.
578
	 * 
579
	 * @return whether or not source is included automatically
580
	 */
581
	public boolean getIncludeSource() {
582
		return fIncludeSource;
583
	}
584
585
	/**
586
	 * Return whether or not the given target has a matching profile that is in sync
587
	 * @param target the target to check
588
	 * @return whether or not the target has been resolved at the p2 level
589
	 */
590
	public static boolean isResolved(ITargetDefinition target) {
591
		P2TargetUtils synchronizer = getSynchronizer(target);
592
		if (synchronizer == null)
593
			return false;
594
		try {
595
			return synchronizer.checkProfile();
596
		} catch (CoreException e) {
597
			return false;
598
		}
599
	}
600
601
	/**
602
	 * Get the synchronizer to use for the given target.  If there is already one on a
603
	 * container in the target, use that one.  Otherwise, create a new one.  Either way, 
604
	 * ensure that all other IU containers in the target are using the same synchronizer.
605
	 * <p>
606
	 * The synchronizer is an instance of {@link P2TargetUtils} that has access to the 
607
	 * profile and other p2 bits for the target.
608
	 * </p>
609
	 * 
610
	 * @param target the target for which we are getting the synchronizer
611
	 * @return the discovered or created synchronizer
612
	 */
613
	static synchronized P2TargetUtils getSynchronizer(ITargetDefinition target) {
614
		IBundleContainer[] containers = target.getBundleContainers();
615
		P2TargetUtils result = null;
616
		// if there are no containers then just create/return the synchronizer
617
		if (containers == null) {
618
			return new P2TargetUtils(target);
619
		}
620
621
		// Otherwise, look for a pre-existing synchronizer
622
		for (int i = 0; i < containers.length; i++) {
623
			if (containers[i] instanceof IUBundleContainer) {
624
				result = ((IUBundleContainer) containers[i]).getSynchronizer(null);
625
				if (result != null) {
626
					break;
428
				}
627
				}
429
			}
628
			}
430
			if (recreate) {
629
		}
431
				P2TargetUtils.deleteProfile(handle);
630
432
				profile = null;
631
		// still no luck?  create a new one
433
			}
632
		if (result == null) {
434
		}
633
			result = new P2TargetUtils(target);
435
		if (profile == null) {
634
		}
436
			// create profile
635
437
			Map properties = new HashMap();
636
		// finally set all the other IU containers to use the same synchronizer
438
			properties.put(IProfile.PROP_INSTALL_FOLDER, P2TargetUtils.INSTALL_FOLDERS.append(Long.toString(LocalTargetHandle.nextTimeStamp())).toOSString());
637
		for (int i = 0; i < containers.length; i++) {
439
			properties.put(IProfile.PROP_CACHE, P2TargetUtils.BUNDLE_POOL.toOSString());
638
			if (containers[i] instanceof IUBundleContainer) {
440
			properties.put(IProfile.PROP_INSTALL_FEATURES, Boolean.TRUE.toString());
639
				((IUBundleContainer) containers[i]).setSynchronizer(result);
441
			// set up environment & NL properly so OS specific fragments are down loaded/installed
640
			}
442
			properties.put(IProfile.PROP_ENVIRONMENTS, generateEnvironmentProperties(target));
641
		}
443
			properties.put(IProfile.PROP_NL, generateNLProperty(target));
642
		return result;
444
			String mode = getProvisionMode(target);
643
	}
445
			if (mode != null) {
644
446
				properties.put(P2TargetUtils.PROP_PROVISION_MODE, mode);
645
	/**
447
				properties.put(P2TargetUtils.PROP_ALL_ENVIRONMENTS, Boolean.toString(isAllEnvironments(target)));
646
	 * Return the set of IUs in all IU containers associated with this synchronizer.
647
	 * This is a helper method so we don't have to expose the profile itself.
648
	 * 
649
	 * @param target the target definition to query
650
	 * @param monitor the progress monitor to use
651
	 * @return the set of associated IUs
652
	 * @throws CoreException if there is a problem discovering the IUs
653
	 */
654
	public static IQueryResult getIUs(ITargetDefinition target, IProgressMonitor monitor) throws CoreException {
655
		P2TargetUtils synchronizer = getSynchronizer(target);
656
		if (synchronizer == null)
657
			return null;
658
		synchronizer.synchronize(monitor);
659
		return synchronizer.getProfile().query(QueryUtil.createIUAnyQuery(), null);
660
	}
661
662
	/**
663
	 * Synchronize the profile and the target definition managed by this synchronizer.  On return the profile will 
664
	 * be resolved and correctly match the given target.  The IUBundleContainers associated with 
665
	 * the target will be notified of any changes in the underlying p2 profile and given an 
666
	 * opportunity to update themselves accordingly.
667
	 * 
668
	 * NOTE: this is a potentially *very* heavyweight operation.
669
	 * 
670
	 * NOTE: this method is synchronized as it is effectively a "test and set" caching method. Two
671
	 * threads getting the profile at the same time should not execute concurrently or the profiles
672
	 * will get out of sync.
673
	 * 
674
	 * @throws CoreException if there was a problem synchronizing
675
	 */
676
	public synchronized void synchronize(IProgressMonitor monitor) throws CoreException {
677
		SubMonitor progress = SubMonitor.convert(monitor, 100);
678
679
		// Happiness if we have a profile and it checks out or if we can load one and it checks out.
680
		if (fProfile == null) {
681
			fProfile = getProfileRegistry().getProfile(getProfileId(fTarget));
682
			if (fProfile != null && checkProfile()) {
683
				// if we just loaded the profile for the first time, refresh the container caches
684
				notify(progress.newChild(25));
685
				return;
686
			}
687
		} else if (checkProfile()) {
688
			return;
689
		}
690
691
		// Either no profile was found or it was stale.  Delete the current profile and recreate.  
692
		// This keeps the internal agent data clean and does not cost us much.
693
		deleteProfile(fTarget.getHandle());
694
		createProfile();
695
696
		if (progress.isCanceled())
697
			return;
698
		progress.setWorkRemaining(75);
699
700
		// Now resolve the profile and refresh the relate IU containers
701
		if (getIncludeAllRequired())
702
			resolveWithPlanner(progress.newChild(60));
703
		else
704
			resolveWithSlicer(progress.newChild(60));
705
706
		// If we are updating a profile then delete the old snapshot on success.
707
		notify(progress.newChild(15));
708
		fDirty = false;
709
	}
710
711
	private void createProfile() throws CoreException, ProvisionException {
712
		// create a new profile
713
		IProfileRegistry registry = getProfileRegistry();
714
		if (registry == null) {
715
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.AbstractTargetHandle_0));
716
		}
717
		Map properties = new HashMap();
718
		properties.put(IProfile.PROP_INSTALL_FOLDER, INSTALL_FOLDERS.append(Long.toString(LocalTargetHandle.nextTimeStamp())).toOSString());
719
		properties.put(IProfile.PROP_CACHE, BUNDLE_POOL.toOSString());
720
		properties.put(IProfile.PROP_INSTALL_FEATURES, Boolean.TRUE.toString());
721
		properties.put(IProfile.PROP_ENVIRONMENTS, generateEnvironmentProperties(fTarget));
722
		properties.put(IProfile.PROP_NL, generateNLProperty(fTarget));
723
		properties.put(PROP_SEQUENCE_NUMBER, Integer.toString(fTarget.currentSequenceNumber()));
724
		properties.put(PROP_PROVISION_MODE, getProvisionMode(fTarget));
725
		properties.put(PROP_ALL_ENVIRONMENTS, Boolean.toString(getIncludeAllEnvironments()));
726
		properties.put(PROP_AUTO_INCLUDE_SOURCE, Boolean.toString(getIncludeSource()));
727
		fProfile = registry.addProfile(getProfileId(fTarget), properties);
728
	}
729
730
	/**
731
	 * Signal the relevant bundle containers that the given profile has changed.
732
	 */
733
	private void notify(IProgressMonitor monitor) throws CoreException {
734
		// flush the target caches first since some of them are used in rebuilding
735
		// the container caches (e.g., featureModels)
736
		((TargetDefinition) fTarget).flushCaches(P2TargetUtils.BUNDLE_POOL.toOSString());
737
		// Now proactively recompute all the related container caches.
738
		IBundleContainer[] containers = fTarget.getBundleContainers();
739
		for (int i = 0; i < containers.length; i++) {
740
			IBundleContainer container = containers[i];
741
			if (container instanceof IUBundleContainer) {
742
				((IUBundleContainer) container).synchronizerChanged();
448
			}
743
			}
449
			profile = registry.addProfile(id, properties);
450
		}
744
		}
451
		return profile;
452
	}
745
	}
453
746
454
	/**
747
	/**
Lines 466-471 Link Here
466
	}
759
	}
467
760
468
	/**
761
	/**
762
	 * Returns the profile identifier for this target handle. There is one profile
763
	 * per target definition.
764
	 * 
765
	 * @return definition the target to lookup
766
	 * @throws CoreException in unable to generate identifier
767
	 */
768
	public static String getProfileId(ITargetDefinition definition) {
769
		try {
770
			return getProfileId(definition.getHandle());
771
		} catch (CoreException e) {
772
			// gotta make sure that this never happens.  all we're doing here is computing a string.
773
			return null;
774
		}
775
	}
776
777
	/**
469
	 * Returns the profile registry or <code>null</code>
778
	 * Returns the profile registry or <code>null</code>
470
	 * 
779
	 * 
471
	 * @return profile registry or <code>null</code>
780
	 * @return profile registry or <code>null</code>
Lines 485-504 Link Here
485
	 * 
794
	 * 
486
	 * @return provisioning mode or <code>null</code>
795
	 * @return provisioning mode or <code>null</code>
487
	 */
796
	 */
488
	private static String getProvisionMode(ITargetDefinition target) {
797
	private String getProvisionMode(ITargetDefinition target) {
489
		IBundleContainer[] containers = target.getBundleContainers();
798
		return getIncludeAllRequired() ? TargetDefinitionPersistenceHelper.MODE_PLANNER : TargetDefinitionPersistenceHelper.MODE_SLICER;
490
		if (containers != null) {
491
			for (int i = 0; i < containers.length; i++) {
492
				if (containers[i] instanceof IUBundleContainer) {
493
					IUBundleContainer iu = (IUBundleContainer) containers[i];
494
					if (iu.getIncludeAllRequired()) {
495
						return TargetDefinitionPersistenceHelper.MODE_PLANNER;
496
					}
497
					return TargetDefinitionPersistenceHelper.MODE_SLICER;
498
				}
499
			}
500
		}
501
		return null;
502
	}
799
	}
503
800
504
	/**
801
	/**
Lines 516-552 Link Here
516
	}
813
	}
517
814
518
	/**
815
	/**
519
	 * Returns the metadata repository with the given URI.
816
	 * Return a queryable on the metadata defined in the given repo locations
520
	 * 
817
	 * 
521
	 * @param uri location
818
	 * @param repos the repos to lookup
522
	 * @return repository
819
	 * @param monitor the progress monitor
523
	 * @throws CoreException
820
	 * @return the set of metadata repositories found
821
	 * @throws CoreException if there is a problem getting the repositories
524
	 */
822
	 */
525
	public static IMetadataRepository getRepository(URI uri) throws CoreException {
823
	static IQueryable getQueryableMetadata(URI[] repos, IProgressMonitor monitor) throws CoreException {
526
		IMetadataRepositoryManager manager = getRepoManager();
824
		IMetadataRepositoryManager manager = getRepoManager();
527
		IMetadataRepository repo = manager.loadRepository(uri, null);
825
		if (repos == null) {
528
		return repo;
826
			repos = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
827
		}
828
829
		IProgressMonitor loadMonitor = new SubProgressMonitor(monitor, 10);
830
		int repoCount = repos.length;
831
		loadMonitor.beginTask(null, repoCount * 10);
832
		List result = new ArrayList(repoCount);
833
		MultiStatus repoStatus = new MultiStatus(PDECore.PLUGIN_ID, 0, Messages.IUBundleContainer_ProblemsLoadingRepositories, null);
834
		for (int i = 0; i < repoCount; ++i) {
835
			try {
836
				result.add(manager.loadRepository(repos[i], new SubProgressMonitor(loadMonitor, 10)));
837
			} catch (ProvisionException e) {
838
				repoStatus.add(e.getStatus());
839
			}
840
		}
841
		loadMonitor.done();
842
843
		if (result.size() != repos.length) {
844
			throw new CoreException(repoStatus);
845
		}
846
		if (result.size() == 1) {
847
			return (IQueryable) result.get(0);
848
		}
849
		return QueryUtil.compoundQueryable(result);
850
	}
851
852
	/**
853
	 * Used to resolve the contents of this container if the user is including all required software.  The p2 planner is used
854
	 * to determine the complete set of IUs required to run the selected software.  If all requirements are met, the bundles
855
	 * are downloaded from the repository into the bundle pool and added to the target definition.
856
	 * 
857
	 * @param monitor for reporting progress
858
	 * @throws CoreException if there is a problem with the requirements or there is a problem downloading
859
	 */
860
	private void resolveWithPlanner(IProgressMonitor monitor) throws CoreException {
861
		SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.IUBundleContainer_0, 200);
862
863
		// Get the root IUs for every relevant container in the target definition
864
		IInstallableUnit[] units = getRootIUs(fTarget);
865
		if (subMonitor.isCanceled()) {
866
			return;
867
		}
868
869
		// create the provisioning plan
870
		IPlanner planner = getPlanner();
871
		IProfileChangeRequest request = planner.createChangeRequest(fProfile);
872
		// first remove everything that was explicitly installed.  Then add it back.  This has the net effect of 
873
		// removing everything that is no longer needed.
874
		computeRemovals(fProfile, request, getIncludeSource());
875
		request.addAll(Arrays.asList(units));
876
		for (int i = 0; i < units.length; i++) {
877
			IInstallableUnit unit = units[i];
878
			request.setInstallableUnitProfileProperty(unit, PROP_INSTALLED_IU, Boolean.toString(true));
879
		}
880
881
		ProvisioningContext context = new ProvisioningContext(getAgent());
882
		context.setMetadataRepositories(getMetadataRepositories(fTarget));
883
		context.setArtifactRepositories(getArtifactRepositories(fTarget));
884
885
		if (subMonitor.isCanceled()) {
886
			return;
887
		}
888
889
		IProvisioningPlan plan = planner.getProvisioningPlan(request, context, subMonitor.newChild(20));
890
		IStatus status = plan.getStatus();
891
		if (!status.isOK()) {
892
			throw new CoreException(status);
893
		}
894
		setPlanProperties(plan, fTarget, TargetDefinitionPersistenceHelper.MODE_PLANNER);
895
		IProvisioningPlan installerPlan = plan.getInstallerPlan();
896
		if (installerPlan != null) {
897
			// this plan requires an update to the installer first, log the fact and attempt
898
			// to continue, we don't want to update the running SDK while provisioning a target
899
			PDECore.log(new Status(IStatus.INFO, PDECore.PLUGIN_ID, Messages.IUBundleContainer_6));
900
		}
901
		subMonitor.worked(10);
902
		if (subMonitor.isCanceled()) {
903
			return;
904
		}
905
906
		// execute the provisioning plan
907
		IPhaseSet phases = createPhaseSet();
908
		IEngine engine = getEngine();
909
		IStatus result = engine.perform(plan, phases, subMonitor.newChild(100));
910
		if (subMonitor.isCanceled()) {
911
			return;
912
		}
913
		if (!result.isOK()) {
914
			throw new CoreException(result);
915
		}
916
917
		// Now that we have a plan with all the binary and explicit bundles, do a second pass and add 
918
		// in all the source.
919
		try {
920
			planInSourceBundles(fProfile, context, subMonitor.newChild(60));
921
		} catch (CoreException e) {
922
			// XXX Review required: is adding in the source critical or optional?
923
			// We failed adding in the source so remove the intermediate profile and rethrow
924
			getProfileRegistry().removeProfile(fProfile.getProfileId(), fProfile.getTimestamp());
925
			throw e;
926
		}
927
	}
928
929
	private void setPlanProperties(IProvisioningPlan plan, ITargetDefinition definition, String mode) {
930
		plan.setProfileProperty(PROP_PROVISION_MODE, mode);
931
		plan.setProfileProperty(PROP_ALL_ENVIRONMENTS, Boolean.toString(getIncludeSource()));
932
		plan.setProfileProperty(PROP_AUTO_INCLUDE_SOURCE, Boolean.toString(getIncludeSource()));
933
		plan.setProfileProperty(PROP_SEQUENCE_NUMBER, Integer.toString(definition.currentSequenceNumber()));
934
	}
935
936
	private IPhaseSet createPhaseSet() {
937
		ArrayList phases = new ArrayList(4);
938
		phases.add(new Collect(100));
939
		phases.add(new Property(1));
940
		phases.add(new Uninstall(50, true));
941
		phases.add(new Install(50));
942
		phases.add(new CollectNativesPhase(100));
943
		return new PhaseSet((Phase[]) phases.toArray(new Phase[phases.size()]));
944
	}
945
946
	/** 
947
	 * Update the given change request to remove anything that was explicitly installed
948
	 * including the internal source IU.  
949
	 */
950
	private void computeRemovals(IProfile profile, IProfileChangeRequest request, boolean includeSource) {
951
		// if include source is off then ensure that the source IU is removed.
952
		if (!includeSource) {
953
			IInstallableUnit sourceIU = getCurrentSourceIU(profile);
954
			if (sourceIU != null)
955
				request.remove(sourceIU);
956
		}
957
		// remove everything that is marked as roots.  The plan will have the new roots added in anyway.
958
		IQuery query = new IUProfilePropertyQuery(PROP_INSTALLED_IU, Boolean.toString(true));
959
		IQueryResult installedIUs = profile.query(query, null);
960
		request.removeAll(installedIUs.toSet());
961
	}
962
963
	// run a second pass of the planner to add in the source bundles for everything that's
964
	// in the current profile.
965
	private void planInSourceBundles(IProfile fProfile, ProvisioningContext context, IProgressMonitor monitor) throws CoreException {
966
		SubMonitor subMonitor = SubMonitor.convert(monitor, "Provisioning source bundles", 100);
967
968
		// create an IU that optionally and greedily requires the related source bundles.
969
		// Completely replace any source IU that may already be in place
970
		IInstallableUnit currentSourceIU = getCurrentSourceIU(fProfile);
971
972
		// determine the new version number.  start at 1
973
		Version sourceVersion = Version.createOSGi(1, 0, 0);
974
		if (currentSourceIU != null) {
975
			Integer major = (Integer) currentSourceIU.getVersion().getSegment(0);
976
			sourceVersion = Version.createOSGi(major.intValue() + 1, 0, 0);
977
		}
978
		IInstallableUnit sourceIU = createSourceIU(fProfile, sourceVersion);
979
980
		// call the planner again to add in the new source IU and all available source bundles
981
		IPlanner planner = getPlanner();
982
		IProfileChangeRequest request = planner.createChangeRequest(fProfile);
983
		if (currentSourceIU != null)
984
			request.remove(currentSourceIU);
985
		request.add(sourceIU);
986
		IProvisioningPlan plan = planner.getProvisioningPlan(request, context, subMonitor.newChild(25));
987
		IStatus status = plan.getStatus();
988
		if (!status.isOK()) {
989
			throw new CoreException(status);
990
		}
991
		if (subMonitor.isCanceled()) {
992
			return;
993
		}
994
995
		// execute the provisioning plan
996
		long oldTimestamp = fProfile.getTimestamp();
997
		IPhaseSet phases = PhaseSetFactory.createDefaultPhaseSetExcluding(new String[] {PhaseSetFactory.PHASE_CHECK_TRUST, PhaseSetFactory.PHASE_CONFIGURE, PhaseSetFactory.PHASE_UNCONFIGURE, PhaseSetFactory.PHASE_UNINSTALL});
998
		IEngine engine = getEngine();
999
		plan.setProfileProperty(PROP_PROVISION_MODE, TargetDefinitionPersistenceHelper.MODE_PLANNER);
1000
		plan.setProfileProperty(PROP_ALL_ENVIRONMENTS, Boolean.toString(false));
1001
		IStatus result = engine.perform(plan, phases, subMonitor.newChild(75));
1002
1003
		if (subMonitor.isCanceled()) {
1004
			return;
1005
		}
1006
		if (!result.isOK()) {
1007
			throw new CoreException(result);
1008
		}
1009
1010
		// remove the old (intermediate) profile version now we have a new one with source.
1011
		getProfileRegistry().removeProfile(fProfile.getProfileId(), oldTimestamp);
1012
	}
1013
1014
	// Create and return an IU that has optional and greedy requirements on all source bundles
1015
	// related to bundle IUs in the given queryable. 
1016
	private IInstallableUnit createSourceIU(IQueryable queryable, Version iuVersion) {
1017
		// compute the set of source bundles we could possibly need for the bundles in the profile
1018
		IRequirement bundleRequirement = MetadataFactory.createRequirement("org.eclipse.equinox.p2.eclipse.type", "bundle", null, null, false, false, false); //$NON-NLS-1$ //$NON-NLS-2$
1019
		IQueryResult profileIUs = queryable.query(QueryUtil.createIUAnyQuery(), null);
1020
		ArrayList requirements = new ArrayList();
1021
		for (Iterator i = profileIUs.iterator(); i.hasNext();) {
1022
			IInstallableUnit profileIU = (IInstallableUnit) i.next();
1023
			if (profileIU.satisfies(bundleRequirement)) {
1024
				String id = profileIU.getId() + ".source"; //$NON-NLS-1$
1025
				Version version = profileIU.getVersion();
1026
				VersionRange range = new VersionRange(version, true, version, true);
1027
				IRequirement sourceRequirement = MetadataFactory.createRequirement("osgi.bundle", id, range, null, true, false, true); //$NON-NLS-1$
1028
				requirements.add(sourceRequirement);
1029
			}
1030
		}
1031
1032
		InstallableUnitDescription sourceDescription = new MetadataFactory.InstallableUnitDescription();
1033
		sourceDescription.setSingleton(true);
1034
		sourceDescription.setId(SOURCE_IU_ID);
1035
		sourceDescription.setVersion(iuVersion);
1036
		sourceDescription.addRequirements(requirements);
1037
		IProvidedCapability capability = MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, SOURCE_IU_ID, iuVersion);
1038
		sourceDescription.setCapabilities(new IProvidedCapability[] {capability});
1039
		return MetadataFactory.createInstallableUnit(sourceDescription);
1040
	}
1041
1042
	// Lookup and return (if any) the source IU in the given queryable.
1043
	private IInstallableUnit getCurrentSourceIU(IQueryable queryable) {
1044
		IQuery query = QueryUtil.createIUQuery(SOURCE_IU_ID);
1045
		IQueryResult list = queryable.query(query, null);
1046
		IInstallableUnit currentSourceIU = null;
1047
		if (!list.isEmpty())
1048
			currentSourceIU = (IInstallableUnit) list.iterator().next();
1049
		return currentSourceIU;
1050
	}
1051
1052
	/**
1053
	 * Used to resolve the contents of this container when the user has chosen to manage the dependencies in the target
1054
	 * themselves.  The selected IUs and any required software that can be found will be retrieved from the repositories 
1055
	 * and added to the target.  Any missing required software will be ignored.
1056
	 * 
1057
	 * @param monitor for reporting progress
1058
	 * @throws CoreException if there is a problem interacting with the repositories
1059
	 */
1060
	private void resolveWithSlicer(IProgressMonitor monitor) throws CoreException {
1061
		SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.IUBundleContainer_0, 100);
1062
1063
		// resolve IUs
1064
		IInstallableUnit[] units = getRootIUs(fTarget);
1065
		if (subMonitor.isCanceled()) {
1066
			return;
1067
		}
1068
1069
		URI[] repositories = getMetadataRepositories(fTarget);
1070
		int repoCount = repositories.length;
1071
		if (repoCount == 0) {
1072
			return;
1073
		}
1074
		IQueryable allMetadata = getQueryableMetadata(repositories, subMonitor.newChild(10));
1075
1076
		// do an initial slice to add everything the user requested
1077
		IQueryResult queryResult = slice(units, allMetadata, fTarget, subMonitor.newChild(10));
1078
		if (subMonitor.isCanceled() || queryResult == null || queryResult.isEmpty()) {
1079
			return;
1080
		}
1081
1082
		// If we are including source then create a source IU to bring in the relevant source
1083
		// bundles and run the slicer again.
1084
		if (getIncludeSource()) {
1085
			// Build an IU that represents all the source bundles and slice again to add them in if available
1086
			IInstallableUnit sourceIU = createSourceIU(queryResult, Version.createOSGi(1, 0, 0));
1087
			IInstallableUnit[] units2 = new IInstallableUnit[units.length + 1];
1088
			System.arraycopy(units, 0, units2, 0, units.length);
1089
			units2[units.length] = sourceIU;
1090
1091
			queryResult = slice(units2, allMetadata, fTarget, subMonitor.newChild(10));
1092
			if (subMonitor.isCanceled() || queryResult == null || queryResult.isEmpty()) {
1093
				return;
1094
			}
1095
		}
1096
1097
		IEngine engine = getEngine();
1098
		ProvisioningContext context = new ProvisioningContext(getAgent());
1099
		context.setMetadataRepositories(repositories);
1100
		context.setArtifactRepositories(getArtifactRepositories(fTarget));
1101
		IProvisioningPlan plan = engine.createPlan(fProfile, context);
1102
		setPlanProperties(plan, fTarget, TargetDefinitionPersistenceHelper.MODE_SLICER);
1103
1104
		Set newSet = queryResult.toSet();
1105
		Iterator itor = newSet.iterator();
1106
		while (itor.hasNext()) {
1107
			plan.addInstallableUnit((IInstallableUnit) itor.next());
1108
		}
1109
		for (int i = 0; i < units.length; i++) {
1110
			IInstallableUnit unit = units[i];
1111
			plan.setInstallableUnitProfileProperty(unit, PROP_INSTALLED_IU, Boolean.toString(true));
1112
		}
1113
1114
		// remove all units that are in the current profile but not in the new slice
1115
		Set toRemove = fProfile.query(QueryUtil.ALL_UNITS, null).toSet();
1116
		toRemove.removeAll(newSet);
1117
		for (Iterator i = toRemove.iterator(); i.hasNext();) {
1118
			plan.removeInstallableUnit((IInstallableUnit) i.next());
1119
		}
1120
1121
		if (subMonitor.isCanceled()) {
1122
			return;
1123
		}
1124
		subMonitor.worked(10);
1125
1126
		// execute the provisioning plan
1127
		IPhaseSet phases = createPhaseSet();
1128
		IStatus result = engine.perform(plan, phases, subMonitor.newChild(60));
1129
		if (!result.isOK()) {
1130
			throw new CoreException(result);
1131
		}
1132
	}
1133
1134
	private IQueryResult slice(IInstallableUnit[] units, IQueryable allMetadata, ITargetDefinition definition, IProgressMonitor monitor) throws CoreException {
1135
		SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
1136
		// slice IUs and all prerequisites
1137
		PermissiveSlicer slicer = null;
1138
		if (getIncludeAllEnvironments()) {
1139
			slicer = new PermissiveSlicer(allMetadata, new HashMap(), true, false, true, true, false);
1140
		} else {
1141
			Map props = new HashMap();
1142
			props.put("osgi.os", definition.getOS() != null ? definition.getOS() : Platform.getOS()); //$NON-NLS-1$
1143
			props.put("osgi.ws", definition.getWS() != null ? definition.getWS() : Platform.getWS()); //$NON-NLS-1$
1144
			props.put("osgi.arch", definition.getArch() != null ? definition.getArch() : Platform.getOSArch()); //$NON-NLS-1$
1145
			props.put("osgi.nl", definition.getNL() != null ? definition.getNL() : Platform.getNL()); //$NON-NLS-1$
1146
			props.put(IProfile.PROP_INSTALL_FEATURES, Boolean.TRUE.toString());
1147
			slicer = new PermissiveSlicer(allMetadata, props, true, false, false, true, false);
1148
		}
1149
		IQueryable slice = slicer.slice(units, subMonitor.newChild(50));
1150
		if (!slicer.getStatus().isOK()) {
1151
			throw new CoreException(slicer.getStatus());
1152
		}
1153
		IQueryResult queryResult = null;
1154
		if (slice != null)
1155
			queryResult = slice.query(QueryUtil.createIUAnyQuery(), subMonitor.newChild(50));
1156
		return queryResult;
1157
	}
1158
1159
	/**
1160
	 * Returns the artifact repositories to consider when getting artifacts.  Returns a default set of
1161
	 * repositories if current repository settings are <code>null</code>).
1162
	 *  
1163
	 * @return URI's of repositories to use when getting artifacts
1164
	 * @exception CoreException
1165
	 */
1166
	private URI[] getArtifactRepositories(ITargetDefinition target) throws CoreException {
1167
		Set result = new HashSet();
1168
		IBundleContainer[] containers = target.getBundleContainers();
1169
		IArtifactRepositoryManager manager = getArtifactRepositoryManager();
1170
		for (int i = 0; i < containers.length; i++) {
1171
			IBundleContainer container = containers[i];
1172
			if (container instanceof IUBundleContainer) {
1173
				URI[] repos = ((IUBundleContainer) container).getRepositories();
1174
				if (repos == null) {
1175
					repos = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
1176
				}
1177
				result.addAll(Arrays.asList(repos));
1178
			}
1179
		}
1180
		if (useAdditionalLocalArtifacts()) {
1181
			// get all the artifact repos we know in the manager currently
1182
			result.addAll(Arrays.asList(manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL)));
1183
1184
			// Add in the IDE profile bundle pool and all known workspaces
1185
			findProfileRepos(result);
1186
			findWorkspaceRepos(result);
1187
		}
1188
		return (URI[]) result.toArray(new URI[result.size()]);
529
	}
1189
	}
530
1190
531
	/**
1191
	/**
532
	 * Returns whether software site containers are configured to provision for all environments
1192
	 * return whether or not to use local artifact repositories when provisioning the target
533
	 * versus a single environment.
1193
	 */
1194
	private boolean useAdditionalLocalArtifacts() {
1195
		// XXX consider using a preference here or another strategy if users are able to spec 
1196
		// what local repos are to be considered.
1197
		return true;
1198
	}
1199
1200
	/** 
1201
	 * Add the artifact repos from the PDE target bundle pools from all known repos.  For example, the list 
1202
	 * of "recent workspaces" maintained by the IDE is a good source.
534
	 * 
1203
	 * 
535
	 * @return whether all environments will be provisioned
1204
	 * @param additionalRepos the set to which additional repos are added.
536
	 */
1205
	 */
537
	private static boolean isAllEnvironments(ITargetDefinition target) {
1206
	private void findWorkspaceRepos(Set additionalRepos) {
1207
		IPreferencesService prefs = getPreferences();
1208
		if (prefs == null)
1209
			return;
1210
		String recent = prefs.getString("org.eclipse.ui.ide", "RECENT_WORKSPACES", null, null); //$NON-NLS-1$ //$NON-NLS-2$
1211
		if (recent == null)
1212
			return;
1213
		String[] recents = recent.split("\n"); //$NON-NLS-1$
1214
		for (int i = 0; i < recents.length; i++) {
1215
			String bundlePool = recents[i] + "/.metadata/.plugins/org.eclipse.pde.core/.bundle_pool"; //$NON-NLS-1$
1216
			if (new File(bundlePool).exists()) {
1217
				URI uri;
1218
				try {
1219
					uri = new URI("file", bundlePool, null); //$NON-NLS-1$
1220
					additionalRepos.add(uri);
1221
				} catch (URISyntaxException e) {
1222
					// should never happen
1223
				}
1224
			}
1225
		}
1226
	}
1227
1228
	/** 
1229
	 * Look through the current p2 profile (_SELF_) and add the artifact repos that make up its
1230
	 * bundle pool, dropins location, ...  This helps in the cases that you are targeting stuff that 
1231
	 * makes up your current IDE.
1232
	 * 
1233
	 * @param additionalRepos the set to which additional repos are added.
1234
	 */
1235
	private void findProfileRepos(Set additionalRepos) {
1236
		try {
1237
			// NOTE: be sure to use the global p2 agent here as we are looking for SELF.
1238
			IProfileRegistry profileRegistry = (IProfileRegistry) getGlobalAgent().getService(IProfileRegistry.SERVICE_NAME);
1239
			if (profileRegistry == null)
1240
				return;
1241
			IProfile self = profileRegistry.getProfile(IProfileRegistry.SELF);
1242
			if (self == null)
1243
				return;
1244
1245
			IAgentLocation location = (IAgentLocation) getGlobalAgent().getService(IAgentLocation.SERVICE_NAME);
1246
			URI dataArea = location.getDataArea("org.eclipse.equinox.p2.engine"); //$NON-NLS-1$
1247
			dataArea = URIUtil.append(dataArea, "profileRegistry/" + self.getProfileId() + ".profile"); //$NON-NLS-1$//$NON-NLS-2$
1248
			ProfileMetadataRepository profileRepo = new ProfileMetadataRepository(getGlobalAgent(), dataArea, null);
1249
			Collection repos = profileRepo.getReferences();
1250
			for (Iterator i = repos.iterator(); i.hasNext();) {
1251
				Object element = i.next();
1252
				if (element instanceof IRepositoryReference) {
1253
					IRepositoryReference reference = (IRepositoryReference) element;
1254
					if (reference.getType() == IRepository.TYPE_ARTIFACT && reference.getLocation() != null)
1255
						additionalRepos.add(reference.getLocation());
1256
				}
1257
			}
1258
		} catch (CoreException e) {
1259
			// if there is a problem, move on.  Could log something here 
1260
			return;
1261
		}
1262
	}
1263
1264
	/**
1265
	 * Returns the IU's for the given target related to the given containers
1266
	 * 
1267
	 * @param containers the bundle containers to filter with
1268
	 * @return the discovered IUs
1269
	 * @exception CoreException if unable to retrieve IU's
1270
	 */
1271
	private IInstallableUnit[] getRootIUs(ITargetDefinition definition) throws CoreException {
1272
		HashSet result = new HashSet();
1273
		IBundleContainer[] containers = definition.getBundleContainers();
1274
		for (int i = 0; i < containers.length; i++) {
1275
			IBundleContainer container = containers[i];
1276
			if (container instanceof IUBundleContainer) {
1277
				IUBundleContainer iuContainer = (IUBundleContainer) container;
1278
				IQueryable repos = getQueryableMetadata(iuContainer.getRepositories(), new NullProgressMonitor());
1279
				String[] ids = iuContainer.getIds();
1280
				Version[] versions = iuContainer.getVersions();
1281
				for (int j = 0; j < ids.length; j++) {
1282
					IQuery query = QueryUtil.createIUQuery(ids[j], versions[j]);
1283
					IQueryResult queryResult = repos.query(query, null);
1284
					if (queryResult.isEmpty())
1285
						throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, NLS.bind(Messages.IUBundleContainer_1, ids[j])));
1286
					result.add(queryResult.iterator().next());
1287
				}
1288
			}
1289
		}
1290
		return (IInstallableUnit[]) result.toArray(new IInstallableUnit[result.size()]);
1291
	}
1292
1293
	/**
1294
	 * Returns the repositories to consider when resolving IU's (will return default set of
1295
	 * repositories if current repository settings are <code>null</code>).
1296
	 *  
1297
	 * @return URI's of repositories to use when resolving bundles
1298
	 * @exception CoreException
1299
	 */
1300
	private URI[] getMetadataRepositories(ITargetDefinition target) throws CoreException {
1301
		Set result = new HashSet();
538
		IBundleContainer[] containers = target.getBundleContainers();
1302
		IBundleContainer[] containers = target.getBundleContainers();
539
		if (containers != null) {
1303
		IMetadataRepositoryManager manager = getRepoManager();
540
			for (int i = 0; i < containers.length; i++) {
1304
		for (int i = 0; i < containers.length; i++) {
541
				if (containers[i] instanceof IUBundleContainer) {
1305
			IBundleContainer container = containers[i];
542
					IUBundleContainer iu = (IUBundleContainer) containers[i];
1306
			if (container instanceof IUBundleContainer) {
543
					if (iu.getIncludeAllEnvironments()) {
1307
				URI[] repos = ((IUBundleContainer) container).getRepositories();
544
						return true;
1308
				if (repos == null) {
545
					}
1309
					repos = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
546
				}
1310
				}
1311
				result.addAll(Arrays.asList(repos));
1312
			}
1313
		}
1314
		return (URI[]) result.toArray(new URI[result.size()]);
1315
	}
1316
1317
	private static final String NATIVE_ARTIFACTS = "nativeArtifacts"; //$NON-NLS-1$
1318
	private static final String NATIVE_TYPE = "org.eclipse.equinox.p2.native"; //$NON-NLS-1$
1319
	private static final String PARM_OPERAND = "operand"; //$NON-NLS-1$
1320
1321
	protected static class CollectNativesAction extends ProvisioningAction {
1322
		public IStatus execute(Map parameters) {
1323
			InstallableUnitOperand operand = (InstallableUnitOperand) parameters.get(PARM_OPERAND);
1324
			IInstallableUnit installableUnit = operand.second();
1325
			if (installableUnit == null)
1326
				return Status.OK_STATUS;
1327
1328
			IArtifactRepositoryManager manager;
1329
			try {
1330
				Collection toDownload = installableUnit.getArtifacts();
1331
				if (toDownload == null)
1332
					return Status.OK_STATUS;
1333
1334
				List artifactRequests = (List) parameters.get(NATIVE_ARTIFACTS);
1335
				IArtifactRepository destinationArtifactRepository = getBundlePool();
1336
				manager = getArtifactRepositoryManager();
1337
				for (Iterator i = toDownload.iterator(); i.hasNext();) {
1338
					IArtifactKey keyToDownload = (IArtifactKey) i.next();
1339
					IArtifactRequest request = manager.createMirrorRequest(keyToDownload, destinationArtifactRepository, null, null);
1340
					artifactRequests.add(request);
1341
				}
1342
			} catch (CoreException e) {
1343
				return e.getStatus();
1344
			}
1345
			return Status.OK_STATUS;
1346
		}
1347
1348
		public IStatus undo(Map parameters) {
1349
			// nothing to do for now
1350
			return Status.OK_STATUS;
1351
		}
1352
	}
1353
1354
	protected static class CollectNativesPhase extends InstallableUnitPhase {
1355
		public CollectNativesPhase(int weight) {
1356
			super(NATIVE_ARTIFACTS, weight);
1357
		}
1358
1359
		protected List getActions(InstallableUnitOperand operand) {
1360
			IInstallableUnit unit = operand.second();
1361
			if (unit != null && unit.getTouchpointType().getId().equals(NATIVE_TYPE)) {
1362
				return Collections.singletonList(new CollectNativesAction());
547
			}
1363
			}
1364
			return null;
1365
		}
1366
1367
		protected IStatus initializePhase(IProgressMonitor monitor, IProfile profile, Map parameters) {
1368
			parameters.put(NATIVE_ARTIFACTS, new ArrayList());
1369
			parameters.put(PARM_PROFILE, profile);
1370
			return null;
1371
		}
1372
1373
		protected IStatus completePhase(IProgressMonitor monitor, IProfile profile, Map parameters) {
1374
			List artifactRequests = (List) parameters.get(NATIVE_ARTIFACTS);
1375
			ProvisioningContext context = (ProvisioningContext) parameters.get(PARM_CONTEXT);
1376
			IProvisioningAgent agent = (IProvisioningAgent) parameters.get(PARM_AGENT);
1377
			DownloadManager dm = new DownloadManager(context, agent);
1378
			for (Iterator i = artifactRequests.iterator(); i.hasNext();) {
1379
				dm.add((IArtifactRequest) i.next());
1380
			}
1381
			return dm.start(monitor);
548
		}
1382
		}
549
		return false;
550
	}
1383
	}
551
1384
1385
	/**
1386
	 * @return the profile associated with this synchronizer
1387
	 */
1388
	IProfile getProfile() {
1389
		return fProfile;
1390
	}
1391
1392
	/**
1393
	 * @return the target definition associated with this synchronizer
1394
	 */
1395
	ITargetDefinition getTargetDefinition() {
1396
		return fTarget;
1397
	}
1398
1399
	void markDirty() {
1400
		fDirty = true;
1401
	}
552
}
1402
}
(-)src/org/eclipse/pde/internal/core/target/TargetDefinition.java (+63 lines)
Lines 75-80 Link Here
75
	private IFeatureModel[] fFeatureModels;
75
	private IFeatureModel[] fFeatureModels;
76
	private IResolvedBundle[] fOtherBundles;
76
	private IResolvedBundle[] fOtherBundles;
77
77
78
	private int fSequenceNumber = -1;
79
78
	/**
80
	/**
79
	 * Constructs a target definition based on the given handle. 
81
	 * Constructs a target definition based on the given handle. 
80
	 */
82
	 */
Lines 142-147 Link Here
142
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#setArch(java.lang.String)
144
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#setArch(java.lang.String)
143
	 */
145
	 */
144
	public void setArch(String arch) {
146
	public void setArch(String arch) {
147
		incrementSequenceNumber();
145
		fArch = arch;
148
		fArch = arch;
146
	}
149
	}
147
150
Lines 149-154 Link Here
149
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#setNL(java.lang.String)
152
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#setNL(java.lang.String)
150
	 */
153
	 */
151
	public void setNL(String nl) {
154
	public void setNL(String nl) {
155
		incrementSequenceNumber();
152
		fNL = nl;
156
		fNL = nl;
153
	}
157
	}
154
158
Lines 163-168 Link Here
163
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#setOS(java.lang.String)
167
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#setOS(java.lang.String)
164
	 */
168
	 */
165
	public void setOS(String os) {
169
	public void setOS(String os) {
170
		incrementSequenceNumber();
166
		fOS = os;
171
		fOS = os;
167
	}
172
	}
168
173
Lines 190-195 Link Here
190
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#setWS(java.lang.String)
195
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#setWS(java.lang.String)
191
	 */
196
	 */
192
	public void setWS(String ws) {
197
	public void setWS(String ws) {
198
		incrementSequenceNumber();
193
		fWS = ws;
199
		fWS = ws;
194
	}
200
	}
195
201
Lines 197-202 Link Here
197
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#setBundleContainers(org.eclipse.pde.internal.core.target.provisional.IBundleContainer[])
203
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#setBundleContainers(org.eclipse.pde.internal.core.target.provisional.IBundleContainer[])
198
	 */
204
	 */
199
	public void setBundleContainers(IBundleContainer[] containers) {
205
	public void setBundleContainers(IBundleContainer[] containers) {
206
		incrementSequenceNumber();
200
		// Clear the feature model cache as it is based on the bundle container locations
207
		// Clear the feature model cache as it is based on the bundle container locations
201
		fFeatureModels = null;
208
		fFeatureModels = null;
202
		fOtherBundles = null;
209
		fOtherBundles = null;
Lines 210-215 Link Here
210
		if (containers == null) {
217
		if (containers == null) {
211
			fIncluded = null;
218
			fIncluded = null;
212
			fOptional = null;
219
			fOptional = null;
220
		} else {
221
			for (int i = 0; i < containers.length; i++) {
222
				((AbstractBundleContainer) containers[i]).associateWithTarget(this);
223
			}
224
		}
225
	}
226
227
	/**
228
	 * Clears the any models that are cached for the given container location.
229
	 * 
230
	 * @param location location to clear cache for or <code>null</code> to clear all cached models
231
	 */
232
	public void flushCaches(String location) {
233
		// Clear the feature model cache as it is based on the bundle container locations
234
		fFeatureModels = null;
235
		fOtherBundles = null;
236
		if (location == null) {
237
			fFeaturesInLocation.clear();
238
		} else {
239
			fFeaturesInLocation.remove(location);
240
		}
241
		if (fContainers == null) {
242
			fIncluded = null;
243
			fOptional = null;
213
		}
244
		}
214
	}
245
	}
215
246
Lines 623-628 Link Here
623
			fProgramArgs = null;
654
			fProgramArgs = null;
624
			fVMArgs = null;
655
			fVMArgs = null;
625
			fWS = null;
656
			fWS = null;
657
			fSequenceNumber = 0;
626
			TargetDefinitionPersistenceHelper.initFromXML(this, stream);
658
			TargetDefinitionPersistenceHelper.initFromXML(this, stream);
627
		} catch (ParserConfigurationException e) {
659
		} catch (ParserConfigurationException e) {
628
			abort(Messages.TargetDefinition_0, e);
660
			abort(Messages.TargetDefinition_0, e);
Lines 994-1004 Link Here
994
		return result;
1026
		return result;
995
	}
1027
	}
996
1028
1029
	/**
1030
	 * @return the current UI style one of {@link #MODE_FEATURE} or {@link #MODE_PLUGIN}
1031
	 */
997
	public int getUIMode() {
1032
	public int getUIMode() {
998
		return fUIMode;
1033
		return fUIMode;
999
	}
1034
	}
1000
1035
1036
	/**
1037
	 * @param mode new UI style to use, one of {@link #MODE_FEATURE} or {@link #MODE_PLUGIN}
1038
	 */
1001
	public void setUIMode(int mode) {
1039
	public void setUIMode(int mode) {
1002
		fUIMode = mode;
1040
		fUIMode = mode;
1003
	}
1041
	}
1042
1043
	/* (non-Javadoc)
1044
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetDefinition#currentSequenceNumber()
1045
	 */
1046
	public int currentSequenceNumber() {
1047
		return fSequenceNumber;
1048
	}
1049
1050
	/**
1051
	 * Increases the current sequence number.
1052
	 * @see TargetDefinition#currentSequenceNumber()
1053
	 * @return the current sequence number after it has been increased
1054
	 */
1055
	public int incrementSequenceNumber() {
1056
		return ++fSequenceNumber;
1057
	}
1058
1059
	/**
1060
	 * Convenience method to set the sequence number to a specific 
1061
	 * value. Used when loading a target from a persisted file.
1062
	 * @param value value to set the sequence number to
1063
	 */
1064
	void setSequenceNumber(int value) {
1065
		fSequenceNumber = value;
1066
	}
1004
}
1067
}
(-)src/org/eclipse/pde/internal/core/target/TargetDefinitionPersistenceHelper.java (+3 lines)
Lines 72-77 Link Here
72
	static final String ATTR_OPTIONAL = "optional"; //$NON-NLS-1$
72
	static final String ATTR_OPTIONAL = "optional"; //$NON-NLS-1$
73
	static final String ATTR_VERSION = "version"; //$NON-NLS-1$
73
	static final String ATTR_VERSION = "version"; //$NON-NLS-1$
74
	static final String ATTR_CONFIGURATION = "configuration"; //$NON-NLS-1$
74
	static final String ATTR_CONFIGURATION = "configuration"; //$NON-NLS-1$
75
	static final String ATTR_SEQUENCE_NUMBER = "sequenceNumber"; //$NON-NLS-1$
75
	static final String CONTENT = "content"; //$NON-NLS-1$
76
	static final String CONTENT = "content"; //$NON-NLS-1$
76
	static final String ATTR_USE_ALL = "useAllPlugins"; //$NON-NLS-1$
77
	static final String ATTR_USE_ALL = "useAllPlugins"; //$NON-NLS-1$
77
	static final String PLUGINS = "plugins"; //$NON-NLS-1$
78
	static final String PLUGINS = "plugins"; //$NON-NLS-1$
Lines 107-112 Link Here
107
			rootElement.setAttribute(ATTR_INCLUDE_MODE, FEATURE);
108
			rootElement.setAttribute(ATTR_INCLUDE_MODE, FEATURE);
108
		}
109
		}
109
110
111
		rootElement.setAttribute(ATTR_SEQUENCE_NUMBER, Integer.toString(definition.currentSequenceNumber()));
112
110
		IBundleContainer[] containers = definition.getBundleContainers();
113
		IBundleContainer[] containers = definition.getBundleContainers();
111
		if (containers != null && containers.length > 0) {
114
		if (containers != null && containers.length > 0) {
112
			Element containersElement = doc.createElement(LOCATIONS);
115
			Element containersElement = doc.createElement(LOCATIONS);
(-)src/org/eclipse/pde/internal/core/target/TargetPersistence35Helper.java (-9 / +5 lines)
Lines 224-241 Link Here
224
			String[] iuIDs = (String[]) ids.toArray(new String[ids.size()]);
224
			String[] iuIDs = (String[]) ids.toArray(new String[ids.size()]);
225
			String[] iuVer = (String[]) versions.toArray(new String[versions.size()]);
225
			String[] iuVer = (String[]) versions.toArray(new String[versions.size()]);
226
			URI[] uris = (URI[]) repos.toArray(new URI[repos.size()]);
226
			URI[] uris = (URI[]) repos.toArray(new URI[repos.size()]);
227
			container = new IUBundleContainer(iuIDs, iuVer, uris);
227
			int flags = IUBundleContainer.INCLUDE_REQUIRED;
228
			if (includeMode != null && includeMode.trim().length() > 0) {
228
			if (includeMode != null && includeMode.trim().length() > 0) {
229
				if (includeMode.equals(TargetDefinitionPersistenceHelper.MODE_PLANNER)) {
229
				if (includeMode.equals(TargetDefinitionPersistenceHelper.MODE_SLICER)) {
230
					((IUBundleContainer) container).setIncludeAllRequired(true, null);
230
					flags = 0;
231
				} else if (includeMode.equals(TargetDefinitionPersistenceHelper.MODE_SLICER)) {
232
					((IUBundleContainer) container).setIncludeAllRequired(false, null);
233
				}
231
				}
234
			}
232
			}
235
			if (includeAllPlatforms != null && includeAllPlatforms.trim().length() > 0) {
233
			flags |= Boolean.valueOf(includeAllPlatforms).booleanValue() ? IUBundleContainer.INCLUDE_ALL_ENVIRONMENTS : 0;
236
				((IUBundleContainer) container).setIncludeAllEnvironments(Boolean.valueOf(includeAllPlatforms).booleanValue(), null);
234
			container = new IUBundleContainer(iuIDs, iuVer, uris, flags);
237
			}
238
239
		}
235
		}
240
236
241
		NodeList list = location.getChildNodes();
237
		NodeList list = location.getChildNodes();
(-)src/org/eclipse/pde/internal/core/target/TargetPersistence36Helper.java (-10 / +15 lines)
Lines 148-153 Link Here
148
				}
148
				}
149
			}
149
			}
150
		}
150
		}
151
152
		// Set the sequence number at the very end
153
		String sequenceNumber = root.getAttribute(TargetDefinitionPersistenceHelper.ATTR_SEQUENCE_NUMBER);
154
		try {
155
			((TargetDefinition) definition).setSequenceNumber(Integer.parseInt(sequenceNumber));
156
		} catch (NumberFormatException e) {
157
			((TargetDefinition) definition).setSequenceNumber(0);
158
		}
151
	}
159
	}
152
160
153
	/**
161
	/**
Lines 215-233 Link Here
215
			String[] iuIDs = (String[]) ids.toArray(new String[ids.size()]);
223
			String[] iuIDs = (String[]) ids.toArray(new String[ids.size()]);
216
			String[] iuVer = (String[]) versions.toArray(new String[versions.size()]);
224
			String[] iuVer = (String[]) versions.toArray(new String[versions.size()]);
217
			URI[] uris = (URI[]) repos.toArray(new URI[repos.size()]);
225
			URI[] uris = (URI[]) repos.toArray(new URI[repos.size()]);
218
			container = new IUBundleContainer(iuIDs, iuVer, uris);
226
227
			int flags = IUBundleContainer.INCLUDE_REQUIRED;
219
			if (includeMode != null && includeMode.trim().length() > 0) {
228
			if (includeMode != null && includeMode.trim().length() > 0) {
220
				if (includeMode.equals(TargetDefinitionPersistenceHelper.MODE_PLANNER)) {
229
				if (includeMode.equals(TargetDefinitionPersistenceHelper.MODE_SLICER)) {
221
					((IUBundleContainer) container).setIncludeAllRequired(true, null);
230
					flags = 0;
222
				} else if (includeMode.equals(TargetDefinitionPersistenceHelper.MODE_SLICER)) {
223
					((IUBundleContainer) container).setIncludeAllRequired(false, null);
224
				}
231
				}
225
			}
232
			}
226
			if (includeAllPlatforms != null && includeAllPlatforms.trim().length() > 0) {
233
			flags |= Boolean.valueOf(includeAllPlatforms).booleanValue() ? IUBundleContainer.INCLUDE_ALL_ENVIRONMENTS : 0;
227
				((IUBundleContainer) container).setIncludeAllEnvironments(Boolean.valueOf(includeAllPlatforms).booleanValue(), null);
234
			flags |= Boolean.valueOf(includeSource).booleanValue() ? IUBundleContainer.INCLUDE_SOURCE : 0;
228
			}
235
			container = new IUBundleContainer(iuIDs, iuVer, uris, flags);
229
			((IUBundleContainer) container).setIncludeSource(Boolean.valueOf(includeSource).booleanValue());
230
231
		}
236
		}
232
		return container;
237
		return container;
233
	}
238
	}
(-)src/org/eclipse/pde/internal/core/target/TargetPlatformService.java (-6 / +6 lines)
Lines 591-606 Link Here
591
	}
591
	}
592
592
593
	/* (non-Javadoc)
593
	/* (non-Javadoc)
594
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetPlatformService#newIUContainer(org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit[], java.net.URI[])
594
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetPlatformService#newIUContainer(org.eclipse.equinox.p2.metadata.IInstallableUnit[], java.net.URI[], int)
595
	 */
595
	 */
596
	public IBundleContainer newIUContainer(IInstallableUnit[] units, URI[] repositories) {
596
	public IBundleContainer newIUContainer(IInstallableUnit[] units, URI[] repositories, int resolutionFlags) {
597
		return new IUBundleContainer(units, repositories);
597
		return new IUBundleContainer(units, repositories, resolutionFlags);
598
	}
598
	}
599
599
600
	/* (non-Javadoc)
600
	/* (non-Javadoc)
601
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetPlatformService#newIUContainer(java.lang.String[], java.lang.String[], java.net.URI[])
601
	 * @see org.eclipse.pde.internal.core.target.provisional.ITargetPlatformService#newIUContainer(java.lang.String[], java.lang.String[], java.net.URI[], int)
602
	 */
602
	 */
603
	public IBundleContainer newIUContainer(String[] unitIds, String[] versions, URI[] repositories) {
603
	public IBundleContainer newIUContainer(String[] unitIds, String[] versions, URI[] repositories, int resolutionFlags) {
604
		return new IUBundleContainer(unitIds, versions, repositories);
604
		return new IUBundleContainer(unitIds, versions, repositories, resolutionFlags);
605
	}
605
	}
606
}
606
}
(-)src/org/eclipse/pde/internal/core/target/UpdateTargetJob.java (-3 / +2 lines)
Lines 73-89 Link Here
73
	 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
73
	 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
74
	 */
74
	 */
75
	protected IStatus run(IProgressMonitor monitor) {
75
	protected IStatus run(IProgressMonitor monitor) {
76
		int totalWork = toUpdate.size();
76
		SubMonitor progress = SubMonitor.convert(monitor, Messages.UpdateTargetJob_UpdatingTarget, toUpdate.size());
77
		result = 0;
77
		result = 0;
78
		try {
78
		try {
79
			monitor.beginTask(Messages.UpdateTargetJob_UpdatingTarget, totalWork);
80
			for (Iterator i = toUpdate.entrySet().iterator(); i.hasNext();) {
79
			for (Iterator i = toUpdate.entrySet().iterator(); i.hasNext();) {
81
				try {
80
				try {
82
					Map.Entry entry = (Map.Entry) i.next();
81
					Map.Entry entry = (Map.Entry) i.next();
83
					IBundleContainer container = (IBundleContainer) entry.getKey();
82
					IBundleContainer container = (IBundleContainer) entry.getKey();
84
					monitor.subTask(NLS.bind(Messages.UpdateTargetJob_UpdatingContainer, ((AbstractBundleContainer) container).getLocation(false)));
83
					monitor.subTask(NLS.bind(Messages.UpdateTargetJob_UpdatingContainer, ((AbstractBundleContainer) container).getLocation(false)));
85
					if (container instanceof IUBundleContainer)
84
					if (container instanceof IUBundleContainer)
86
						result |= ((IUBundleContainer) container).update((Set) entry.getValue());
85
						result |= ((IUBundleContainer) container).update((Set) entry.getValue(), progress.newChild(1));
87
				} catch (CoreException e1) {
86
				} catch (CoreException e1) {
88
					return e1.getStatus();
87
					return e1.getStatus();
89
				} finally {
88
				} finally {
(-)src/org/eclipse/pde/internal/core/target/provisional/ITargetDefinition.java (+9 lines)
Lines 320-323 Link Here
320
	 * @return implicit dependencies or <code>null</code>
320
	 * @return implicit dependencies or <code>null</code>
321
	 */
321
	 */
322
	public NameVersionDescriptor[] getImplicitDependencies();
322
	public NameVersionDescriptor[] getImplicitDependencies();
323
324
	/**
325
	 * Returns the current sequence number of this target.  Sequence numbers change
326
	 * whenever something in the target that affects the set of features and bundles that 
327
	 * would be resolved.
328
	 * 
329
	 * @return the current sequence number
330
	 */
331
	public int currentSequenceNumber();
323
}
332
}
(-)src/org/eclipse/pde/internal/core/target/provisional/ITargetPlatformService.java (-4 / +6 lines)
Lines 10-20 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.core.target.provisional;
11
package org.eclipse.pde.internal.core.target.provisional;
12
12
13
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
14
15
import java.net.URI;
13
import java.net.URI;
16
import org.eclipse.core.resources.IFile;
14
import org.eclipse.core.resources.IFile;
17
import org.eclipse.core.runtime.*;
15
import org.eclipse.core.runtime.*;
16
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
17
import org.eclipse.pde.internal.core.target.IUBundleContainer;
18
18
19
/**
19
/**
20
 * A service to manage target platform definitions available to the workspace.
20
 * A service to manage target platform definitions available to the workspace.
Lines 139-147 Link Here
139
	 * @param units installable units
139
	 * @param units installable units
140
	 * @param repositories URI's describing repository locations or <code>null</code> to use
140
	 * @param repositories URI's describing repository locations or <code>null</code> to use
141
	 * 	default repositories
141
	 * 	default repositories
142
	 * @param resolutionFlags bitmask of flags to control IU resolution, possible flags are {@link IUBundleContainer#INCLUDE_ALL_ENVIRONMENTS}, {@link IUBundleContainer#INCLUDE_REQUIRED}, {@link IUBundleContainer#INCLUDE_SOURCE}
142
	 * @return bundle container
143
	 * @return bundle container
143
	 */
144
	 */
144
	public IBundleContainer newIUContainer(IInstallableUnit[] units, URI[] repositories);
145
	public IBundleContainer newIUContainer(IInstallableUnit[] units, URI[] repositories, int resolutionFlags);
145
146
146
	/**
147
	/**
147
	 * Creates and returns a bundle container that contains all bundles contained in
148
	 * Creates and returns a bundle container that contains all bundles contained in
Lines 152-160 Link Here
152
	 * @param versions version identifiers
153
	 * @param versions version identifiers
153
	 * @param repositories URI's describing repository locations or <code>null</code> to use
154
	 * @param repositories URI's describing repository locations or <code>null</code> to use
154
	 * 	default repositories
155
	 * 	default repositories
156
	 * @param resolutionFlags bitmask of flags to control IU resolution, possible flags are {@link IUBundleContainer#INCLUDE_ALL_ENVIRONMENTS}, {@link IUBundleContainer#INCLUDE_REQUIRED}, {@link IUBundleContainer#INCLUDE_SOURCE}
155
	 * @return bundle container
157
	 * @return bundle container
156
	 */
158
	 */
157
	public IBundleContainer newIUContainer(String[] unitIds, String[] versions, URI[] repositories);
159
	public IBundleContainer newIUContainer(String[] unitIds, String[] versions, URI[] repositories, int resolutionFlags);
158
160
159
	/**
161
	/**
160
	 * Creates and returns a bundle container that contains all bundles referenced by
162
	 * Creates and returns a bundle container that contains all bundles referenced by
(-)META-INF/MANIFEST.MF (-1 / +1 lines)
Lines 108-114 Link Here
108
 org.eclipse.pde.launching;bundle-version="[3.6.0,4.0.0)";visibility:=reexport,
108
 org.eclipse.pde.launching;bundle-version="[3.6.0,4.0.0)";visibility:=reexport,
109
 org.eclipse.ui.console;bundle-version="[3.5.0,4.0.0)",
109
 org.eclipse.ui.console;bundle-version="[3.5.0,4.0.0)",
110
 org.eclipse.equinox.simpleconfigurator;bundle-version="[1.0.200,2.0.0)",
110
 org.eclipse.equinox.simpleconfigurator;bundle-version="[1.0.200,2.0.0)",
111
 org.eclipse.equinox.p2.repository.tools
111
 org.eclipse.equinox.p2.repository.tools;bundle-version="[2.0.100,3.0.0)"
112
Eclipse-LazyStart: true
112
Eclipse-LazyStart: true
113
Import-Package: com.ibm.icu.text,
113
Import-Package: com.ibm.icu.text,
114
 org.eclipse.jdt.debug.core
114
 org.eclipse.jdt.debug.core
(-)src/org/eclipse/pde/internal/ui/search/dialogs/FilteredIUSelectionDialog.java (-5 / +11 lines)
Lines 13-19 Link Here
13
import java.util.Comparator;
13
import java.util.Comparator;
14
import java.util.Iterator;
14
import java.util.Iterator;
15
import org.eclipse.core.runtime.*;
15
import org.eclipse.core.runtime.*;
16
import org.eclipse.equinox.p2.core.IProvisioningAgent;
17
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
16
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
18
import org.eclipse.equinox.p2.metadata.IProvidedCapability;
17
import org.eclipse.equinox.p2.metadata.IProvidedCapability;
19
import org.eclipse.equinox.p2.query.IQuery;
18
import org.eclipse.equinox.p2.query.IQuery;
Lines 24-29 Link Here
24
import org.eclipse.jface.viewers.*;
23
import org.eclipse.jface.viewers.*;
25
import org.eclipse.pde.internal.core.PDECore;
24
import org.eclipse.pde.internal.core.PDECore;
26
import org.eclipse.pde.internal.core.target.Messages;
25
import org.eclipse.pde.internal.core.target.Messages;
26
import org.eclipse.pde.internal.core.target.P2TargetUtils;
27
import org.eclipse.pde.internal.ui.*;
27
import org.eclipse.pde.internal.ui.*;
28
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.SWT;
29
import org.eclipse.swt.events.SelectionAdapter;
29
import org.eclipse.swt.events.SelectionAdapter;
Lines 67-72 Link Here
67
				styledString.append("(", StyledString.QUALIFIER_STYLER); //$NON-NLS-1$
67
				styledString.append("(", StyledString.QUALIFIER_STYLER); //$NON-NLS-1$
68
				styledString.append(iuPackage.getVersion().toString(), StyledString.QUALIFIER_STYLER);
68
				styledString.append(iuPackage.getVersion().toString(), StyledString.QUALIFIER_STYLER);
69
				styledString.append(")", StyledString.QUALIFIER_STYLER); //$NON-NLS-1$
69
				styledString.append(")", StyledString.QUALIFIER_STYLER); //$NON-NLS-1$
70
				IInstallableUnit iu = iuPackage.getIU();
71
				styledString.append(" from ", StyledString.QUALIFIER_STYLER); //$NON-NLS-1$
72
				styledString.append(iu.getId(), StyledString.QUALIFIER_STYLER);
73
				styledString.append(' ');
74
				styledString.append("(", StyledString.QUALIFIER_STYLER); //$NON-NLS-1$
75
				styledString.append(iu.getVersion().toString(), StyledString.QUALIFIER_STYLER);
76
				styledString.append(")", StyledString.QUALIFIER_STYLER); //$NON-NLS-1$
70
			} else if (element instanceof IInstallableUnit) {
77
			} else if (element instanceof IInstallableUnit) {
71
				IInstallableUnit iu = (IInstallableUnit) element;
78
				IInstallableUnit iu = (IInstallableUnit) element;
72
				String name = iu.getProperty(IInstallableUnit.PROP_NAME, null);
79
				String name = iu.getProperty(IInstallableUnit.PROP_NAME, null);
Lines 190-199 Link Here
190
	 */
197
	 */
191
	protected void fillContentProvider(AbstractContentProvider contentProvider, ItemsFilter itemsFilter, IProgressMonitor progressMonitor) throws CoreException {
198
	protected void fillContentProvider(AbstractContentProvider contentProvider, ItemsFilter itemsFilter, IProgressMonitor progressMonitor) throws CoreException {
192
		// TODO clean up this code a bit...
199
		// TODO clean up this code a bit...
193
		IProvisioningAgent agent = (IProvisioningAgent) PDECore.getDefault().acquireService(IProvisioningAgent.SERVICE_NAME);
200
		IMetadataRepositoryManager manager = P2TargetUtils.getRepoManager();
194
		if (agent == null)
201
		if (manager == null)
195
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_7));
202
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_2));
196
		IMetadataRepositoryManager manager = (IMetadataRepositoryManager) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
197
203
198
		//URI[] knownRepositories = metadataManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
204
		//URI[] knownRepositories = metadataManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
199
		IQuery pipedQuery;
205
		IQuery pipedQuery;
(-)src/org/eclipse/pde/internal/ui/search/dialogs/TargetRepositorySearchHandler.java (-3 / +2 lines)
Lines 78-87 Link Here
78
		ITargetPlatformService service = (ITargetPlatformService) PDECore.getDefault().acquireService(ITargetPlatformService.class.getName());
78
		ITargetPlatformService service = (ITargetPlatformService) PDECore.getDefault().acquireService(ITargetPlatformService.class.getName());
79
		ITargetHandle currentTarget = service.getWorkspaceTargetHandle();
79
		ITargetHandle currentTarget = service.getWorkspaceTargetHandle();
80
		ITargetDefinition definition = currentTarget.getTargetDefinition();
80
		ITargetDefinition definition = currentTarget.getTargetDefinition();
81
		IUBundleContainer container = (IUBundleContainer) service.newIUContainer(units, repositories);
82
		// Force the target into slicer mode as all requirements may not be available
81
		// Force the target into slicer mode as all requirements may not be available
83
		container.setIncludeAllRequired(false, definition);
82
		int flags = IUBundleContainer.INCLUDE_ALL_ENVIRONMENTS | IUBundleContainer.INCLUDE_SOURCE;
84
		container.setIncludeAllEnvironments(true, definition);
83
		IUBundleContainer container = (IUBundleContainer) service.newIUContainer(units, repositories, flags);
85
		IBundleContainer[] oldContainers = definition.getBundleContainers();
84
		IBundleContainer[] oldContainers = definition.getBundleContainers();
86
		if (oldContainers == null) {
85
		if (oldContainers == null) {
87
			definition.setBundleContainers(new IBundleContainer[] {container});
86
			definition.setBundleContainers(new IBundleContainer[] {container});
(-)src/org/eclipse/pde/internal/ui/shared/target/AddBundleContainerSelectionPage.java (-10 / +1 lines)
Lines 14-25 Link Here
14
import java.util.ArrayList;
14
import java.util.ArrayList;
15
import java.util.List;
15
import java.util.List;
16
import org.eclipse.core.runtime.*;
16
import org.eclipse.core.runtime.*;
17
import org.eclipse.equinox.p2.engine.IProfile;
18
import org.eclipse.jface.dialogs.*;
17
import org.eclipse.jface.dialogs.*;
19
import org.eclipse.jface.viewers.*;
18
import org.eclipse.jface.viewers.*;
20
import org.eclipse.jface.wizard.*;
19
import org.eclipse.jface.wizard.*;
21
import org.eclipse.pde.internal.core.PDECore;
20
import org.eclipse.pde.internal.core.PDECore;
22
import org.eclipse.pde.internal.core.target.P2TargetUtils;
23
import org.eclipse.pde.internal.core.target.provisional.*;
21
import org.eclipse.pde.internal.core.target.provisional.*;
24
import org.eclipse.pde.internal.ui.*;
22
import org.eclipse.pde.internal.ui.*;
25
import org.eclipse.pde.internal.ui.wizards.WizardElement;
23
import org.eclipse.pde.internal.ui.wizards.WizardElement;
Lines 291-304 Link Here
291
							settings = PDEPlugin.getDefault().getDialogSettings().addNewSection(SETTINGS_SECTION);
289
							settings = PDEPlugin.getDefault().getDialogSettings().addNewSection(SETTINGS_SECTION);
292
						}
290
						}
293
						setDialogSettings(settings);
291
						setDialogSettings(settings);
294
						// TODO Use proper API to get the profile
292
						addPage(new EditIUContainerPage(fTarget));
295
						IProfile profile = null;
296
						try {
297
							profile = P2TargetUtils.getProfile(fTarget);
298
						} catch (CoreException e) {
299
							PDEPlugin.log(e);
300
						}
301
						addPage(new EditIUContainerPage(fTarget, profile));
302
					}
293
					}
303
294
304
					public boolean performFinish() {
295
					public boolean performFinish() {
(-)src/org/eclipse/pde/internal/ui/shared/target/EditBundleContainerWizard.java (-6 / +1 lines)
Lines 10-16 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.ui.shared.target;
11
package org.eclipse.pde.internal.ui.shared.target;
12
12
13
import org.eclipse.core.runtime.CoreException;
14
import org.eclipse.jface.dialogs.IDialogSettings;
13
import org.eclipse.jface.dialogs.IDialogSettings;
15
import org.eclipse.jface.wizard.Wizard;
14
import org.eclipse.jface.wizard.Wizard;
16
import org.eclipse.pde.internal.core.target.*;
15
import org.eclipse.pde.internal.core.target.*;
Lines 50-60 Link Here
50
		} else if (fContainer instanceof FeatureBundleContainer) {
49
		} else if (fContainer instanceof FeatureBundleContainer) {
51
			fPage = new EditFeatureContainerPage(fContainer);
50
			fPage = new EditFeatureContainerPage(fContainer);
52
		} else if (fContainer instanceof IUBundleContainer) {
51
		} else if (fContainer instanceof IUBundleContainer) {
53
			try {
52
			fPage = new EditIUContainerPage((IUBundleContainer) fContainer, fTarget);
54
				fPage = new EditIUContainerPage((IUBundleContainer) fContainer, fTarget, P2TargetUtils.getProfile(fTarget));
55
			} catch (CoreException e) {
56
				PDEPlugin.log(e);
57
			}
58
		}
53
		}
59
		if (fPage != null) {
54
		if (fPage != null) {
60
			addPage(fPage);
55
			addPage(fPage);
(-)src/org/eclipse/pde/internal/ui/shared/target/EditIUContainerPage.java (-38 / +36 lines)
Lines 18-24 Link Here
18
import org.eclipse.equinox.internal.p2.ui.actions.PropertyDialogAction;
18
import org.eclipse.equinox.internal.p2.ui.actions.PropertyDialogAction;
19
import org.eclipse.equinox.internal.p2.ui.dialogs.*;
19
import org.eclipse.equinox.internal.p2.ui.dialogs.*;
20
import org.eclipse.equinox.internal.p2.ui.query.IUViewQueryContext;
20
import org.eclipse.equinox.internal.p2.ui.query.IUViewQueryContext;
21
import org.eclipse.equinox.p2.engine.IProfile;
22
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
21
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
23
import org.eclipse.equinox.p2.ui.Policy;
22
import org.eclipse.equinox.p2.ui.Policy;
24
import org.eclipse.equinox.p2.ui.ProvisioningUI;
23
import org.eclipse.equinox.p2.ui.ProvisioningUI;
Lines 30-35 Link Here
30
import org.eclipse.osgi.util.NLS;
29
import org.eclipse.osgi.util.NLS;
31
import org.eclipse.pde.internal.core.PDECore;
30
import org.eclipse.pde.internal.core.PDECore;
32
import org.eclipse.pde.internal.core.target.IUBundleContainer;
31
import org.eclipse.pde.internal.core.target.IUBundleContainer;
32
import org.eclipse.pde.internal.core.target.P2TargetUtils;
33
import org.eclipse.pde.internal.core.target.provisional.*;
33
import org.eclipse.pde.internal.core.target.provisional.*;
34
import org.eclipse.pde.internal.ui.*;
34
import org.eclipse.pde.internal.ui.*;
35
import org.eclipse.swt.SWT;
35
import org.eclipse.swt.SWT;
Lines 68-78 Link Here
68
	private IUBundleContainer fEditContainer;
68
	private IUBundleContainer fEditContainer;
69
69
70
	/**
70
	/**
71
	 * Profile from the target
72
	 */
73
	private IProfile fProfile;
74
75
	/**
76
	 * Used to provide special attributes/filtering to the available iu group 
71
	 * Used to provide special attributes/filtering to the available iu group 
77
	 */
72
	 */
78
	private IUViewQueryContext fQueryContext;
73
	private IUViewQueryContext fQueryContext;
Lines 97-115 Link Here
97
92
98
	/**
93
	/**
99
	 * Constructor for creating a new container
94
	 * Constructor for creating a new container
100
	 * @param profile profile from the parent target, used to setup the p2 UI
95
	 * @param definition the target definintion we are editing
101
	 */
96
	 */
102
	protected EditIUContainerPage(ITargetDefinition definition, IProfile profile) {
97
	protected EditIUContainerPage(ITargetDefinition definition) {
103
		super("AddP2Container"); //$NON-NLS-1$
98
		super("AddP2Container"); //$NON-NLS-1$
104
		setTitle(Messages.EditIUContainerPage_5);
99
		setTitle(Messages.EditIUContainerPage_5);
105
		setMessage(Messages.EditIUContainerPage_6);
100
		setMessage(Messages.EditIUContainerPage_6);
106
		fTarget = definition;
101
		fTarget = definition;
107
		fProfile = profile;
108
		ProvisioningUI selfProvisioningUI = ProvisioningUI.getDefaultUI();
102
		ProvisioningUI selfProvisioningUI = ProvisioningUI.getDefaultUI();
109
		// TODO we use the service session from the self profile.  In the future we may want
103
		// TODO we use the service session from the self profile.  In the future we may want
110
		// to set up our own services for the profile (separate repo managers, etc).
104
		// to set up our own services for the profile (separate repo managers, etc).
111
		// We use our own new policy so we don't bash the SDK's settings.
105
		// We use our own new policy so we don't bash the SDK's settings.
112
		profileUI = new ProvisioningUI(selfProvisioningUI.getSession(), profile.getProfileId(), new Policy());
106
		profileUI = new ProvisioningUI(selfProvisioningUI.getSession(), P2TargetUtils.getProfileId(definition), new Policy());
113
	}
107
	}
114
108
115
	/**
109
	/**
Lines 117-124 Link Here
117
	 * @param container the container to edit
111
	 * @param container the container to edit
118
	 * @param profile profile from the parent target, used to setup the p2 UI
112
	 * @param profile profile from the parent target, used to setup the p2 UI
119
	 */
113
	 */
120
	protected EditIUContainerPage(IUBundleContainer container, ITargetDefinition definition, IProfile profile) {
114
	protected EditIUContainerPage(IUBundleContainer container, ITargetDefinition definition) {
121
		this(definition, profile);
115
		this(definition);
122
		setTitle(Messages.EditIUContainerPage_7);
116
		setTitle(Messages.EditIUContainerPage_7);
123
		setMessage(Messages.EditIUContainerPage_6);
117
		setMessage(Messages.EditIUContainerPage_6);
124
		fEditContainer = container;
118
		fEditContainer = container;
Lines 132-141 Link Here
132
		if (service == null) {
126
		if (service == null) {
133
			PDEPlugin.log(new Status(IStatus.ERROR, PDEPlugin.getPluginId(), Messages.EditIUContainerPage_9));
127
			PDEPlugin.log(new Status(IStatus.ERROR, PDEPlugin.getPluginId(), Messages.EditIUContainerPage_9));
134
		}
128
		}
135
		IUBundleContainer container = (IUBundleContainer) service.newIUContainer(fAvailableIUGroup.getCheckedLeafIUs(), fRepoLocation != null ? new URI[] {fRepoLocation} : null);
129
		int flags = fIncludeRequiredButton.getSelection() ? IUBundleContainer.INCLUDE_REQUIRED : 0;
136
		container.setIncludeAllRequired(fIncludeRequiredButton.getSelection(), fTarget);
130
		flags |= fAllPlatformsButton.getSelection() ? IUBundleContainer.INCLUDE_ALL_ENVIRONMENTS : 0;
137
		container.setIncludeAllEnvironments(fAllPlatformsButton.getSelection(), fTarget);
131
		flags |= fIncludeSourceButton.getSelection() ? IUBundleContainer.INCLUDE_SOURCE : 0;
138
		container.setIncludeSource(fIncludeSourceButton.getSelection());
132
		IUBundleContainer container = (IUBundleContainer) service.newIUContainer(fAvailableIUGroup.getCheckedLeafIUs(), fRepoLocation != null ? new URI[] {fRepoLocation} : null, flags);
139
		return container;
133
		return container;
140
	}
134
	}
141
135
Lines 299-330 Link Here
299
		});
293
		});
300
		((GridData) fAllPlatformsButton.getLayoutData()).horizontalIndent = 10;
294
		((GridData) fAllPlatformsButton.getLayoutData()).horizontalIndent = 10;
301
		fIncludeSourceButton = SWTFactory.createCheckButton(slicerGroup, Messages.EditIUContainerPage_16, null, true, 1);
295
		fIncludeSourceButton = SWTFactory.createCheckButton(slicerGroup, Messages.EditIUContainerPage_16, null, true, 1);
296
		fIncludeSourceButton.addSelectionListener(new SelectionAdapter() {
297
			public void widgetSelected(SelectionEvent e) {
298
				warnIfGlobalSettingChanged();
299
			}
300
		});
302
	}
301
	}
303
302
304
	private void warnIfGlobalSettingChanged() {
303
	private void warnIfGlobalSettingChanged() {
305
		boolean warn = false;
304
		boolean noChange = true;
306
		if (fTarget != null) {
305
		IUBundleContainer iuContainer = null;
307
			IBundleContainer[] containers = fTarget.getBundleContainers();
306
		IBundleContainer[] containers = fTarget.getBundleContainers();
308
			if (containers != null) {
307
		if (containers != null) {
309
				for (int i = 0; i < containers.length; i++) {
308
			// Look for a IUBundleContainer to compare against.
310
					if (containers[i] instanceof IUBundleContainer && containers[i] != fEditContainer) {
309
			for (int i = 0; i < containers.length; i++) {
311
						IUBundleContainer container = (IUBundleContainer) containers[i];
310
				if (containers[i] instanceof IUBundleContainer && containers[i] != fEditContainer) {
312
						if (container.getIncludeAllRequired() != fIncludeRequiredButton.getSelection()) {
311
					iuContainer = (IUBundleContainer) containers[i];
313
							warn = true;
312
					break;
314
							break;
315
						}
316
						if (!fIncludeRequiredButton.getSelection() && container.getIncludeAllEnvironments() != fAllPlatformsButton.getSelection()) {
317
							warn = true;
318
							break;
319
						}
320
					}
321
				}
313
				}
322
			}
314
			}
315
			// If there is another IU container then compare against it.  No need to check them all
316
			// as they will all be set the same within one target.
317
			if (iuContainer != null) {
318
				noChange &= fIncludeRequiredButton.getSelection() == iuContainer.getIncludeAllRequired();
319
				noChange &= fAllPlatformsButton.getSelection() == iuContainer.getIncludeAllEnvironments();
320
				noChange &= fIncludeSourceButton.getSelection() == iuContainer.getIncludeSource();
321
			}
323
		}
322
		}
324
		if (warn) {
323
		if (noChange) {
325
			setMessage(Messages.EditIUContainerPage_4, IStatus.WARNING);
326
		} else {
327
			setMessage(Messages.EditIUContainerPage_6);
324
			setMessage(Messages.EditIUContainerPage_6);
325
		} else {
326
			setMessage(Messages.EditIUContainerPage_4, IStatus.WARNING);
328
		}
327
		}
329
	}
328
	}
330
329
Lines 333-339 Link Here
333
	 */
332
	 */
334
	private void createQueryContext() {
333
	private void createQueryContext() {
335
		fQueryContext = ProvUI.getQueryContext(ProvisioningUI.getDefaultUI().getPolicy());
334
		fQueryContext = ProvUI.getQueryContext(ProvisioningUI.getDefaultUI().getPolicy());
336
		fQueryContext.setInstalledProfileId(fProfile.getProfileId());
335
		fQueryContext.setInstalledProfileId(P2TargetUtils.getProfileId(fTarget));
337
		fQueryContext.showAlreadyInstalled();
336
		fQueryContext.showAlreadyInstalled();
338
	}
337
	}
339
338
Lines 498-504 Link Here
498
				// Only able to check items if we don't have categories
497
				// Only able to check items if we don't have categories
499
				fQueryContext.setViewType(IUViewQueryContext.AVAILABLE_VIEW_FLAT);
498
				fQueryContext.setViewType(IUViewQueryContext.AVAILABLE_VIEW_FLAT);
500
				fAvailableIUGroup.updateAvailableViewState();
499
				fAvailableIUGroup.updateAvailableViewState();
501
				fAvailableIUGroup.setChecked(fEditContainer.getInstallableUnits(fProfile));
500
				fAvailableIUGroup.setChecked(fEditContainer.getInstallableUnits());
502
				// Make sure view is back in proper state
501
				// Make sure view is back in proper state
503
				updateViewContext();
502
				updateViewContext();
504
				IInstallableUnit[] units = fAvailableIUGroup.getCheckedLeafIUs();
503
				IInstallableUnit[] units = fAvailableIUGroup.getCheckedLeafIUs();
Lines 519-523 Link Here
519
			}
518
			}
520
		}
519
		}
521
	}
520
	}
522
523
}
521
}
(-)src/org/eclipse/pde/internal/ui/shared/target/TargetContentsGroup.java (-2 / +2 lines)
Lines 1028-1037 Link Here
1028
		if (parent == null) {
1028
		if (parent == null) {
1029
			result = fAllBundles.toArray();
1029
			result = fAllBundles.toArray();
1030
		} else if (fFeaureModeButton.getSelection() && parent == OTHER_CATEGORY) {
1030
		} else if (fFeaureModeButton.getSelection() && parent == OTHER_CATEGORY) {
1031
			return ((TargetDefinition) fTargetDefinition).getOtherBundles();
1031
			result = ((TargetDefinition) fTargetDefinition).getOtherBundles();
1032
		} else if (fGrouping == GROUP_BY_CONTAINER && parent instanceof IBundleContainer) {
1032
		} else if (fGrouping == GROUP_BY_CONTAINER && parent instanceof IBundleContainer) {
1033
			IBundleContainer container = (IBundleContainer) parent;
1033
			IBundleContainer container = (IBundleContainer) parent;
1034
			return container.getBundles();
1034
			result = container.getBundles();
1035
		} else if (fGrouping == GROUP_BY_FILE_LOC && parent instanceof IPath) {
1035
		} else if (fGrouping == GROUP_BY_FILE_LOC && parent instanceof IPath) {
1036
			List bundles = (List) getFileBundleMapping().get(parent);
1036
			List bundles = (List) getFileBundleMapping().get(parent);
1037
			if (bundles != null && bundles.size() > 0) {
1037
			if (bundles != null && bundles.size() > 0) {
(-)src/org/eclipse/pde/internal/ui/shared/target/TargetLocationsGroup.java (-9 / +7 lines)
Lines 10-23 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.ui.shared.target;
11
package org.eclipse.pde.internal.ui.shared.target;
12
12
13
import org.eclipse.pde.internal.core.target.UpdateTargetJob;
14
15
import java.util.*;
13
import java.util.*;
16
import java.util.List;
14
import java.util.List;
17
import org.eclipse.core.runtime.*;
15
import org.eclipse.core.runtime.*;
18
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
16
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
19
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
17
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
20
import org.eclipse.equinox.p2.engine.IProfile;
21
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
18
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
22
import org.eclipse.jface.viewers.*;
19
import org.eclipse.jface.viewers.*;
23
import org.eclipse.jface.window.Window;
20
import org.eclipse.jface.window.Window;
Lines 423-430 Link Here
423
							// do nothing if we could not see the current target.
420
							// do nothing if we could not see the current target.
424
						}
421
						}
425
						updateButtons();
422
						updateButtons();
426
						// XXX still need to figure how to mark the target as dirty so it gets persisted.
427
						// right now it seems to always be dirty
428
					}
423
					}
429
				});
424
				});
430
			}
425
			}
Lines 440-446 Link Here
440
		boolean updateAllowed = false;
435
		boolean updateAllowed = false;
441
		Iterator iter = selection.iterator();
436
		Iterator iter = selection.iterator();
442
		while (iter.hasNext()) {
437
		while (iter.hasNext()) {
443
			if (removeAllowed && updateAllowed){
438
			if (removeAllowed && updateAllowed) {
444
				break;
439
				break;
445
			}
440
			}
446
			Object current = iter.next();
441
			Object current = iter.next();
Lines 495-504 Link Here
495
						}
490
						}
496
					} else if (parentElement instanceof IUBundleContainer) {
491
					} else if (parentElement instanceof IUBundleContainer) {
497
						// Show the IUs as children
492
						// Show the IUs as children
498
						// TODO See if we can get the profile using API
499
						try {
493
						try {
500
							IProfile profile = P2TargetUtils.getProfile(fTarget);
494
							// if this is a bundle container then we must be sure that all bundle containers are
501
							IInstallableUnit[] units = ((IUBundleContainer) parentElement).getInstallableUnits(profile);
495
							// happy since they all share the same profile.
496
							if (!P2TargetUtils.isResolved(fTarget)) {
497
								return new Object[0];
498
							}
499
							IInstallableUnit[] units = ((IUBundleContainer) parentElement).getInstallableUnits();
502
							// Wrap the units so that they remember their parent container
500
							// Wrap the units so that they remember their parent container
503
							List wrappedUnits = new ArrayList(units.length);
501
							List wrappedUnits = new ArrayList(units.length);
504
							for (int i = 0; i < units.length; i++) {
502
							for (int i = 0; i < units.length; i++) {
(-)src/org/eclipse/pde/internal/ui/wizards/exports/ExportTargetJob.java (-7 / +4 lines)
Lines 15-27 Link Here
15
import org.eclipse.core.filesystem.*;
15
import org.eclipse.core.filesystem.*;
16
import org.eclipse.core.runtime.*;
16
import org.eclipse.core.runtime.*;
17
import org.eclipse.core.runtime.jobs.Job;
17
import org.eclipse.core.runtime.jobs.Job;
18
import org.eclipse.equinox.p2.engine.IProfile;
19
import org.eclipse.equinox.p2.internal.repository.tools.Repo2Runnable;
18
import org.eclipse.equinox.p2.internal.repository.tools.Repo2Runnable;
20
import org.eclipse.equinox.p2.internal.repository.tools.RepositoryDescriptor;
19
import org.eclipse.equinox.p2.internal.repository.tools.RepositoryDescriptor;
21
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
20
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
22
import org.eclipse.equinox.p2.metadata.IProvidedCapability;
21
import org.eclipse.equinox.p2.metadata.IProvidedCapability;
23
import org.eclipse.equinox.p2.query.IQueryResult;
22
import org.eclipse.equinox.p2.query.IQueryResult;
24
import org.eclipse.equinox.p2.query.QueryUtil;
25
import org.eclipse.pde.internal.core.feature.ExternalFeatureModel;
23
import org.eclipse.pde.internal.core.feature.ExternalFeatureModel;
26
import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
24
import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
27
import org.eclipse.pde.internal.core.target.IUBundleContainer;
25
import org.eclipse.pde.internal.core.target.IUBundleContainer;
Lines 219-231 Link Here
219
	}
217
	}
220
218
221
	private void exportProfile(ITargetDefinition target, URI destination, IProgressMonitor monitor) throws CoreException {
219
	private void exportProfile(ITargetDefinition target, URI destination, IProgressMonitor monitor) throws CoreException {
222
		IProfile profile = P2TargetUtils.getProfile(target);
223
		Repo2Runnable exporter = new Repo2Runnable();
220
		Repo2Runnable exporter = new Repo2Runnable();
224
		exporter.addDestination(createRepoDescriptor(destination, profile.getProfileId(), RepositoryDescriptor.KIND_METADATA));
221
		exporter.addDestination(createRepoDescriptor(destination, P2TargetUtils.getProfileId(target), RepositoryDescriptor.KIND_METADATA));
225
		exporter.addDestination(createRepoDescriptor(destination, profile.getProfileId(), RepositoryDescriptor.KIND_ARTIFACT));
222
		exporter.addDestination(createRepoDescriptor(destination, P2TargetUtils.getProfileId(target), RepositoryDescriptor.KIND_ARTIFACT));
226
		exporter.addSource(createRepoDescriptor(P2TargetUtils.getBundlePool(profile).getLocation(), null, RepositoryDescriptor.KIND_ARTIFACT));
223
		exporter.addSource(createRepoDescriptor(P2TargetUtils.getBundlePool().getLocation(), null, RepositoryDescriptor.KIND_ARTIFACT));
227
224
228
		IQueryResult ius = profile.query(QueryUtil.createIUAnyQuery(), null);
225
		IQueryResult ius = P2TargetUtils.getIUs(target, monitor);
229
		ArrayList toExport = new ArrayList();
226
		ArrayList toExport = new ArrayList();
230
		for (Iterator i = ius.iterator(); i.hasNext();) {
227
		for (Iterator i = ius.iterator(); i.hasNext();) {
231
			IInstallableUnit iu = (IInstallableUnit) i.next();
228
			IInstallableUnit iu = (IInstallableUnit) i.next();
(-)src/org/eclipse/pde/ui/tests/target/IUBundleContainerTests.java (-35 / +14 lines)
Lines 10-19 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.pde.ui.tests.target;
11
package org.eclipse.pde.ui.tests.target;
12
12
13
import org.eclipse.pde.internal.core.target.P2TargetUtils;
14
15
import java.util.Iterator;
16
17
import java.io.*;
13
import java.io.*;
18
import java.net.URI;
14
import java.net.URI;
19
import java.net.URL;
15
import java.net.URL;
Lines 23-30 Link Here
23
import org.eclipse.core.filesystem.URIUtil;
19
import org.eclipse.core.filesystem.URIUtil;
24
import org.eclipse.core.runtime.*;
20
import org.eclipse.core.runtime.*;
25
import org.eclipse.equinox.internal.p2.core.helpers.URLUtil;
21
import org.eclipse.equinox.internal.p2.core.helpers.URLUtil;
26
import org.eclipse.equinox.p2.core.IProvisioningAgent;
27
import org.eclipse.equinox.p2.engine.*;
28
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
22
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
29
import org.eclipse.equinox.p2.query.IQueryResult;
23
import org.eclipse.equinox.p2.query.IQueryResult;
30
import org.eclipse.equinox.p2.query.QueryUtil;
24
import org.eclipse.equinox.p2.query.QueryUtil;
Lines 89-104 Link Here
89
	}
83
	}
90
	
84
	
91
	public void testResolveUsingProfile() throws Exception {
85
	public void testResolveUsingProfile() throws Exception {
92
		String[] bundleIDs = new String[]{"feature.b.feature.group"};
86
		String[] features1 = new String[]{"feature.b.feature.group"};
87
		String[] features2 = new String[]{"feature.a.feature.group"};
93
		String[] expectedBundles = new String[]{"bundle.a1", "bundle.a2", "bundle.a3", "bundle.b1", "bundle.b2", "bundle.b3"};
88
		String[] expectedBundles = new String[]{"bundle.a1", "bundle.a2", "bundle.a3", "bundle.b1", "bundle.b2", "bundle.b3"};
94
		String[] expectedBundles2 = new String[]{"bundle.b1", "bundle.b2", "bundle.b3"};
89
		String[] expectedBundles2 = new String[]{"bundle.a1", "bundle.a2", "bundle.a3"};
95
90
96
		try { 
91
		try { 
97
92
			// create a target that references just a high level root
98
			IUBundleContainer container = createContainer(bundleIDs);
93
			IUBundleContainer container = createContainer(features1);
99
			ITargetDefinition target = getTargetService().newTarget();
94
			ITargetDefinition target = getTargetService().newTarget();
100
			target.setBundleContainers(new IBundleContainer[]{container});
95
			target.setBundleContainers(new IBundleContainer[]{container});
101
102
			List infos = getAllBundleInfos(target);
96
			List infos = getAllBundleInfos(target);
103
			Set names = collectAllSymbolicNames(infos);
97
			Set names = collectAllSymbolicNames(infos);
104
			assertEquals(expectedBundles.length, infos.size());
98
			assertEquals(expectedBundles.length, infos.size());
Lines 106-129 Link Here
106
				assertTrue("Missing: " + expectedBundles[i], names.contains(expectedBundles[i]));
100
				assertTrue("Missing: " + expectedBundles[i], names.contains(expectedBundles[i]));
107
			}
101
			}
108
102
109
			IProfile profile = P2TargetUtils.getProfile(target);
103
			// Now modify the target to have just a lower level root.  The extra higher level stuff should get removed.
110
104
			container = createContainer(features2);
111
			IProvisioningAgent agent = P2TargetUtils.getAgent();
105
			target.setBundleContainers(new IBundleContainer[]{container});
112
			IEngine engine = P2TargetUtils.getEngine();
113
			IProvisioningPlan plan = engine.createPlan(profile, new ProvisioningContext(agent));
114
			IQueryResult units = profile.query(QueryUtil.ALL_UNITS, null);
115
			for (Iterator iterator = units.iterator(); iterator.hasNext();) {
116
				IInstallableUnit unit = (IInstallableUnit) iterator.next();
117
				if (unit.getId().startsWith("bundle.a")){
118
					plan.removeInstallableUnit(unit);
119
				}
120
			}
121
			IPhaseSet phases = PhaseSetFactory.createDefaultPhaseSetExcluding(new String[] {PhaseSetFactory.PHASE_CHECK_TRUST, PhaseSetFactory.PHASE_CONFIGURE, PhaseSetFactory.PHASE_UNCONFIGURE});
122
			IStatus result = engine.perform(plan, phases, null);
123
124
			assertTrue("Problem while provisioning: " + result.getMessage(), result.isOK());
125
			
126
			target.resolve(null);  // Force the target to reresolve (hopefully using the modified profile)
127
			infos = getAllBundleInfos(target);
106
			infos = getAllBundleInfos(target);
128
			names = collectAllSymbolicNames(infos);
107
			names = collectAllSymbolicNames(infos);
129
			assertEquals(expectedBundles2.length, infos.size());
108
			assertEquals(expectedBundles2.length, infos.size());
Lines 211-218 Link Here
211
	 */
190
	 */
212
	public void testContentEqualNull() throws Exception {		
191
	public void testContentEqualNull() throws Exception {		
213
		ITargetPlatformService service = getTargetService();
192
		ITargetPlatformService service = getTargetService();
214
		IUBundleContainer c3 = (IUBundleContainer) service.newIUContainer(new String[]{"bundle.a1", "bundle.a2"}, new String[]{"1.0.0", "1.0.0"}, null);
193
		IUBundleContainer c3 = (IUBundleContainer) service.newIUContainer(new String[]{"bundle.a1", "bundle.a2"}, new String[]{"1.0.0", "1.0.0"}, null, 0);
215
		IUBundleContainer c4 = (IUBundleContainer) service.newIUContainer(new String[]{"bundle.a1", "bundle.a2"}, new String[]{"1.0.0", "1.0.0"}, null);
194
		IUBundleContainer c4 = (IUBundleContainer) service.newIUContainer(new String[]{"bundle.a1", "bundle.a2"}, new String[]{"1.0.0", "1.0.0"}, null, 0);
216
		assertTrue("Contents should be equivalent", c3.isContentEqual(c4));
195
		assertTrue("Contents should be equivalent", c3.isContentEqual(c4));
217
	}
196
	}
218
	
197
	
Lines 223-230 Link Here
223
	 */
202
	 */
224
	public void testContentNotEqualNull() throws Exception {		
203
	public void testContentNotEqualNull() throws Exception {		
225
		ITargetPlatformService service = getTargetService();
204
		ITargetPlatformService service = getTargetService();
226
		IUBundleContainer c3 = (IUBundleContainer) service.newIUContainer(new String[]{"bundle.a1", "bundle.a2"}, new String[]{"1.0.0", "1.0.0"}, null);
205
		IUBundleContainer c3 = (IUBundleContainer) service.newIUContainer(new String[]{"bundle.a1", "bundle.a2"}, new String[]{"1.0.0", "1.0.0"}, null, 1);
227
		IUBundleContainer c4 = (IUBundleContainer) service.newIUContainer(new String[]{"bundle.b1", "bundle.b2"}, new String[]{"1.0.0", "1.0.0"}, null);
206
		IUBundleContainer c4 = (IUBundleContainer) service.newIUContainer(new String[]{"bundle.b1", "bundle.b2"}, new String[]{"1.0.0", "1.0.0"}, null, 0);
228
		assertFalse("Contents should not be equivalent", c3.isContentEqual(c4));
207
		assertFalse("Contents should not be equivalent", c3.isContentEqual(c4));
229
	}	
208
	}	
230
	
209
	
Lines 356-362 Link Here
356
	 * @throws Exception
335
	 * @throws Exception
357
	 */
336
	 */
358
	protected IUBundleContainer createContainer(IInstallableUnit[] units, URI[] repositories) throws Exception {
337
	protected IUBundleContainer createContainer(IInstallableUnit[] units, URI[] repositories) throws Exception {
359
		return (IUBundleContainer) getTargetService().newIUContainer(units, repositories);
338
		return (IUBundleContainer) getTargetService().newIUContainer(units, repositories, IUBundleContainer.INCLUDE_REQUIRED);
360
	}
339
	}
361
	
340
	
362
	/**
341
	/**
Lines 473-479 Link Here
473
		
452
		
474
		infos = getBundleInfos(c2);
453
		infos = getBundleInfos(c2);
475
		names = collectAllSymbolicNames(infos);
454
		names = collectAllSymbolicNames(infos);
476
		bundleIds = new String[]{"bundle.b1", "bundle.b2", "bundle.b3"};
455
		bundleIds = new String[]{"bundle.a1", "bundle.a2", "bundle.a3", "bundle.b1", "bundle.b2", "bundle.b3"};
477
		assertEquals(bundleIds.length, infos.size());
456
		assertEquals(bundleIds.length, infos.size());
478
		
457
		
479
		for (int i = 0; i < bundleIds.length; i++) {
458
		for (int i = 0; i < bundleIds.length; i++) {
(-)src/org/eclipse/pde/ui/tests/target/TargetDefinitionPersistenceTests.java (-6 / +2 lines)
Lines 236-247 Link Here
236
		IBundleContainer restrictedProfileContainer = getTargetService().newProfileContainer(TargetPlatform.getDefaultLocation(), null);
236
		IBundleContainer restrictedProfileContainer = getTargetService().newProfileContainer(TargetPlatform.getDefaultLocation(), null);
237
	
237
	
238
		// Site bundle containers with different settings
238
		// Site bundle containers with different settings
239
		IUBundleContainer siteContainer = (IUBundleContainer)getTargetService().newIUContainer(new IInstallableUnit[]{}, new URI[]{new URI("TESTURI"), new URI("TESTURI2")});
239
		IUBundleContainer siteContainer = (IUBundleContainer)getTargetService().newIUContainer(new IInstallableUnit[]{}, new URI[]{new URI("TESTURI"), new URI("TESTURI2")}, IUBundleContainer.INCLUDE_ALL_ENVIRONMENTS);
240
		siteContainer.setIncludeAllRequired(false, null);
240
		IUBundleContainer siteContainer2 = (IUBundleContainer)getTargetService().newIUContainer(new String[]{"unit1","unit2"},new String[]{"1.0", "2.0"}, new URI[]{new URI("TESTURI"), new URI("TESTURI2")}, IUBundleContainer.INCLUDE_REQUIRED);
241
		siteContainer.setIncludeAllEnvironments(true, null);
242
		IUBundleContainer siteContainer2 = (IUBundleContainer)getTargetService().newIUContainer(new String[]{"unit1","unit2"},new String[]{"1.0", "2.0"}, new URI[]{new URI("TESTURI"), new URI("TESTURI2")});
243
		siteContainer2.setIncludeAllRequired(true, null);
244
		siteContainer2.setIncludeAllEnvironments(false, null);
245
		
241
		
246
		NameVersionDescriptor[] restrictions = new NameVersionDescriptor[]{
242
		NameVersionDescriptor[] restrictions = new NameVersionDescriptor[]{
247
				new NameVersionDescriptor("org.eclipse.jdt.launching", null),
243
				new NameVersionDescriptor("org.eclipse.jdt.launching", null),
(-)src/org/eclipse/pde/ui/tests/target/TargetDefinitionResolutionTests.java (-22 / +24 lines)
Lines 594-640 Link Here
594
	 */
594
	 */
595
	public void testSiteContainerIncludeSettings() throws Exception{
595
	public void testSiteContainerIncludeSettings() throws Exception{
596
		ITargetDefinition target = getNewTarget();
596
		ITargetDefinition target = getNewTarget();
597
		IUBundleContainer containerA = (IUBundleContainer)getTargetService().newIUContainer(new IInstallableUnit[0], null);
597
		IUBundleContainer containerA = (IUBundleContainer)getTargetService().newIUContainer(new IInstallableUnit[0], null, IUBundleContainer.INCLUDE_REQUIRED);
598
		IUBundleContainer containerB = (IUBundleContainer)getTargetService().newIUContainer(new String[]{"unit1", "unit2"}, new String[]{"1.0","2.0"}, null);
598
		IUBundleContainer containerB = (IUBundleContainer)getTargetService().newIUContainer(new String[]{"unit1", "unit2"}, new String[]{"1.0","2.0"}, null, IUBundleContainer.INCLUDE_REQUIRED);
599
		target.setBundleContainers(new IBundleContainer[]{containerA, containerB});
599
		target.setBundleContainers(new IBundleContainer[]{containerA, containerB});
600
		
600
		
601
		// Check default settings
601
		// Check default settings
602
		assertTrue(containerA.getIncludeAllRequired());
602
		assertTrue(containerA.getIncludeAllRequired());
603
		assertFalse(containerA.getIncludeAllEnvironments());
603
		assertFalse(containerA.getIncludeAllEnvironments());
604
		assertFalse(containerA.getIncludeSource());
604
		assertTrue(containerB.getIncludeAllRequired());
605
		assertTrue(containerB.getIncludeAllRequired());
605
		assertFalse(containerB.getIncludeAllEnvironments());
606
		assertFalse(containerB.getIncludeAllEnvironments());
607
		assertFalse(containerB.getIncludeSource());
606
		
608
		
607
		// Check basic changes
609
		// Check basic changes
608
		containerA.setIncludeAllRequired(false, null);
610
		int flags = IUBundleContainer.INCLUDE_ALL_ENVIRONMENTS | IUBundleContainer.INCLUDE_SOURCE;
609
		containerA.setIncludeAllEnvironments(true, null);
611
		containerA = (IUBundleContainer)getTargetService().newIUContainer(new IInstallableUnit[0], null, flags);
612
		containerB = (IUBundleContainer)getTargetService().newIUContainer(new String[]{"unit1", "unit2"}, new String[]{"1.0","2.0"}, null, flags);
613
		target.setBundleContainers(new IBundleContainer[]{containerA, containerB});
610
		assertFalse(containerA.getIncludeAllRequired());
614
		assertFalse(containerA.getIncludeAllRequired());
611
		assertTrue(containerA.getIncludeAllEnvironments());
615
		assertTrue(containerA.getIncludeAllEnvironments());
612
		containerA.setIncludeAllEnvironments(false, null);
616
		assertTrue(containerA.getIncludeSource());
613
		containerA.setIncludeAllRequired(true, null);
614
		assertTrue(containerA.getIncludeAllRequired());
615
		assertFalse(containerA.getIncludeAllEnvironments());
616
		
617
		
617
		// Check that all containers are updated in the target if target is passed as argument
618
		// Check that all containers are updated in the target if target is passed as argument
618
		containerA.setIncludeAllRequired(false, target);
619
		flags = IUBundleContainer.INCLUDE_ALL_ENVIRONMENTS | IUBundleContainer.INCLUDE_SOURCE;
619
		assertFalse(containerA.getIncludeAllRequired());
620
		containerA = (IUBundleContainer)getTargetService().newIUContainer(new IInstallableUnit[0], null, flags);
620
		assertFalse(containerA.getIncludeAllEnvironments());
621
		flags = IUBundleContainer.INCLUDE_REQUIRED;
621
		assertFalse(containerB.getIncludeAllRequired());
622
		containerB = (IUBundleContainer)getTargetService().newIUContainer(new String[]{"unit1", "unit2"}, new String[]{"1.0","2.0"}, null, flags);
622
		assertFalse(containerB.getIncludeAllEnvironments());
623
623
		containerB.setIncludeAllRequired(true, target);
624
		target.setBundleContainers(new IBundleContainer[]{containerA, containerB});
624
		assertTrue(containerA.getIncludeAllRequired());
625
		assertTrue(containerA.getIncludeAllRequired());
625
		assertFalse(containerA.getIncludeAllEnvironments());
626
		assertFalse(containerA.getIncludeAllEnvironments());
627
		assertFalse(containerA.getIncludeSource());
626
		assertTrue(containerB.getIncludeAllRequired());
628
		assertTrue(containerB.getIncludeAllRequired());
627
		assertFalse(containerB.getIncludeAllEnvironments());
629
		assertFalse(containerB.getIncludeAllEnvironments());
628
		containerA.setIncludeAllEnvironments(true, target);
630
		assertFalse(containerB.getIncludeSource());
629
		assertTrue(containerA.getIncludeAllRequired());
631
632
		// now switch the order of A and B
633
		target.setBundleContainers(new IBundleContainer[]{containerB, containerA});
634
		assertFalse(containerA.getIncludeAllRequired());
630
		assertTrue(containerA.getIncludeAllEnvironments());
635
		assertTrue(containerA.getIncludeAllEnvironments());
631
		assertTrue(containerB.getIncludeAllRequired());
636
		assertTrue(containerA.getIncludeSource());
637
		assertFalse(containerB.getIncludeAllRequired());
632
		assertTrue(containerB.getIncludeAllEnvironments());
638
		assertTrue(containerB.getIncludeAllEnvironments());
633
		containerB.setIncludeAllEnvironments(false, target);
639
		assertTrue(containerB.getIncludeSource());
634
		assertTrue(containerA.getIncludeAllRequired());
635
		assertFalse(containerA.getIncludeAllEnvironments());
636
		assertTrue(containerB.getIncludeAllRequired());
637
		assertFalse(containerB.getIncludeAllEnvironments());
638
	}
640
	}
639
	
641
	
640
	public void testNameVersionDescriptor() {
642
	public void testNameVersionDescriptor() {

Return to bug 331068