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 |
} |