1 /*******************************************************************************
2  * Copyright (c) 2003, 2016 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Danail Nachev -  ProSyst - bug 218625
14  *     Rob Harrop - SpringSource Inc. (bug 247522 and 255520)
15  *******************************************************************************/
16 package org.eclipse.osgi.internal.resolver;
17 
18 import java.io.IOException;
19 import java.net.URL;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import org.eclipse.osgi.framework.util.KeyedElement;
28 import org.eclipse.osgi.service.resolver.BaseDescription;
29 import org.eclipse.osgi.service.resolver.BundleDescription;
30 import org.eclipse.osgi.service.resolver.BundleSpecification;
31 import org.eclipse.osgi.service.resolver.ExportPackageDescription;
32 import org.eclipse.osgi.service.resolver.GenericDescription;
33 import org.eclipse.osgi.service.resolver.GenericSpecification;
34 import org.eclipse.osgi.service.resolver.HostSpecification;
35 import org.eclipse.osgi.service.resolver.ImportPackageSpecification;
36 import org.eclipse.osgi.service.resolver.NativeCodeDescription;
37 import org.eclipse.osgi.service.resolver.NativeCodeSpecification;
38 import org.eclipse.osgi.service.resolver.State;
39 import org.eclipse.osgi.service.resolver.StateWire;
40 import org.eclipse.osgi.service.resolver.VersionConstraint;
41 import org.osgi.framework.Bundle;
42 import org.osgi.framework.BundleReference;
43 import org.osgi.framework.Constants;
44 import org.osgi.framework.wiring.BundleCapability;
45 import org.osgi.framework.wiring.BundleRequirement;
46 import org.osgi.framework.wiring.BundleRevision;
47 import org.osgi.framework.wiring.BundleWire;
48 import org.osgi.framework.wiring.BundleWiring;
49 import org.osgi.resource.Capability;
50 import org.osgi.resource.Requirement;
51 import org.osgi.resource.Wire;
52 
53 public final class BundleDescriptionImpl extends BaseDescriptionImpl implements BundleDescription, KeyedElement {
54 	static final String[] EMPTY_STRING = new String[0];
55 	static final ImportPackageSpecification[] EMPTY_IMPORTS = new ImportPackageSpecification[0];
56 	static final BundleSpecification[] EMPTY_BUNDLESPECS = new BundleSpecification[0];
57 	static final ExportPackageDescription[] EMPTY_EXPORTS = new ExportPackageDescription[0];
58 	static final BundleDescription[] EMPTY_BUNDLEDESCS = new BundleDescription[0];
59 	static final GenericSpecification[] EMPTY_GENERICSPECS = new GenericSpecification[0];
60 	static final GenericDescription[] EMPTY_GENERICDESCS = new GenericDescription[0];
61 	static final RuntimePermission GET_CLASSLOADER_PERM = new RuntimePermission("getClassLoader"); //$NON-NLS-1$
62 
63 	static final int RESOLVED = 0x01;
64 	static final int SINGLETON = 0x02;
65 	static final int REMOVAL_PENDING = 0x04;
66 	static final int FULLY_LOADED = 0x08;
67 	static final int LAZY_LOADED = 0x10;
68 	static final int HAS_DYNAMICIMPORT = 0x20;
69 	static final int ATTACH_FRAGMENTS = 0x40;
70 	static final int DYNAMIC_FRAGMENTS = 0x80;
71 
72 	// set to fully loaded and allow dynamic fragments by default
73 	private volatile int stateBits = FULLY_LOADED | ATTACH_FRAGMENTS | DYNAMIC_FRAGMENTS;
74 
75 	private volatile long bundleId = -1;
76 	volatile HostSpecification host; //null if the bundle is not a fragment. volatile to allow unsynchronized checks for null
77 	private volatile StateImpl containingState;
78 
79 	private volatile int lazyDataOffset = -1;
80 	private volatile int lazyDataSize = -1;
81 
82 	private List<BundleDescription> dependencies;
83 	private List<BundleDescription> dependents;
84 	private String[] mandatory;
85 	private Map<String, Object> attributes;
86 	private Map<String, String> arbitraryDirectives;
87 
88 	private volatile LazyData lazyData;
89 	private volatile int equinox_ee = -1;
90 
91 	private DescriptionWiring bundleWiring;
92 
BundleDescriptionImpl()93 	public BundleDescriptionImpl() {
94 		//
95 	}
96 
getBundleId()97 	public long getBundleId() {
98 		return bundleId;
99 	}
100 
getSymbolicName()101 	public String getSymbolicName() {
102 		return getName();
103 	}
104 
getSupplier()105 	public BundleDescription getSupplier() {
106 		return this;
107 	}
108 
getLocation()109 	public String getLocation() {
110 		LazyData currentData = loadLazyData();
111 		synchronized (this.monitor) {
112 			return currentData.location;
113 		}
114 	}
115 
getPlatformFilter()116 	public String getPlatformFilter() {
117 		LazyData currentData = loadLazyData();
118 		synchronized (this.monitor) {
119 			return currentData.platformFilter;
120 		}
121 	}
122 
getExecutionEnvironments()123 	public String[] getExecutionEnvironments() {
124 		LazyData currentData = loadLazyData();
125 		synchronized (this.monitor) {
126 			if (currentData.executionEnvironments == null)
127 				return EMPTY_STRING;
128 			return currentData.executionEnvironments;
129 		}
130 	}
131 
getImportPackages()132 	public ImportPackageSpecification[] getImportPackages() {
133 		LazyData currentData = loadLazyData();
134 		synchronized (this.monitor) {
135 			if (currentData.importPackages == null)
136 				return EMPTY_IMPORTS;
137 			return currentData.importPackages;
138 		}
139 	}
140 
getAddedDynamicImportPackages()141 	public ImportPackageSpecification[] getAddedDynamicImportPackages() {
142 		LazyData currentData = loadLazyData();
143 		synchronized (this.monitor) {
144 			if (currentData.addedDynamicImports == null)
145 				return EMPTY_IMPORTS;
146 			return currentData.addedDynamicImports.toArray(new ImportPackageSpecification[currentData.addedDynamicImports.size()]);
147 		}
148 	}
149 
getRequiredBundles()150 	public BundleSpecification[] getRequiredBundles() {
151 		LazyData currentData = loadLazyData();
152 		synchronized (this.monitor) {
153 			if (currentData.requiredBundles == null)
154 				return EMPTY_BUNDLESPECS;
155 			return currentData.requiredBundles;
156 		}
157 	}
158 
getGenericRequires()159 	public GenericSpecification[] getGenericRequires() {
160 		LazyData currentData = loadLazyData();
161 		synchronized (this.monitor) {
162 			if (currentData.genericRequires == null)
163 				return EMPTY_GENERICSPECS;
164 			return currentData.genericRequires;
165 		}
166 	}
167 
getGenericCapabilities()168 	public GenericDescription[] getGenericCapabilities() {
169 		LazyData currentData = loadLazyData();
170 		synchronized (this.monitor) {
171 			if (currentData.genericCapabilities == null)
172 				return EMPTY_GENERICDESCS;
173 			return currentData.genericCapabilities;
174 		}
175 	}
176 
getNativeCodeSpecification()177 	public NativeCodeSpecification getNativeCodeSpecification() {
178 		LazyData currentData = loadLazyData();
179 		synchronized (this.monitor) {
180 			return currentData.nativeCode;
181 		}
182 	}
183 
getExportPackages()184 	public ExportPackageDescription[] getExportPackages() {
185 		LazyData currentData = loadLazyData();
186 		synchronized (this.monitor) {
187 			return currentData.exportPackages == null ? EMPTY_EXPORTS : currentData.exportPackages;
188 		}
189 	}
190 
isResolved()191 	public boolean isResolved() {
192 		return (stateBits & RESOLVED) != 0;
193 	}
194 
getContainingState()195 	public State getContainingState() {
196 		return containingState;
197 	}
198 
getFragments()199 	public BundleDescription[] getFragments() {
200 		if (host != null)
201 			return EMPTY_BUNDLEDESCS;
202 		StateImpl currentState = (StateImpl) getContainingState();
203 		if (currentState == null)
204 			throw new IllegalStateException("BundleDescription does not belong to a state."); //$NON-NLS-1$
205 		return currentState.getFragments(this);
206 	}
207 
getHost()208 	public HostSpecification getHost() {
209 		return host;
210 	}
211 
isSingleton()212 	public boolean isSingleton() {
213 		return (stateBits & SINGLETON) != 0;
214 	}
215 
isRemovalPending()216 	public boolean isRemovalPending() {
217 		return (stateBits & REMOVAL_PENDING) != 0;
218 	}
219 
hasDynamicImports()220 	public boolean hasDynamicImports() {
221 		return (stateBits & HAS_DYNAMICIMPORT) != 0;
222 	}
223 
attachFragments()224 	public boolean attachFragments() {
225 		return (stateBits & ATTACH_FRAGMENTS) != 0;
226 	}
227 
dynamicFragments()228 	public boolean dynamicFragments() {
229 		return (stateBits & DYNAMIC_FRAGMENTS) != 0;
230 	}
231 
getSelectedExports()232 	public ExportPackageDescription[] getSelectedExports() {
233 		LazyData currentData = loadLazyData();
234 		synchronized (this.monitor) {
235 			if (currentData.selectedExports == null)
236 				return EMPTY_EXPORTS;
237 			return currentData.selectedExports;
238 		}
239 	}
240 
getSelectedGenericCapabilities()241 	public GenericDescription[] getSelectedGenericCapabilities() {
242 		LazyData currentData = loadLazyData();
243 		synchronized (this.monitor) {
244 			if (currentData.selectedCapabilities == null)
245 				return EMPTY_GENERICDESCS;
246 			return currentData.selectedCapabilities;
247 		}
248 	}
249 
getSubstitutedExports()250 	public ExportPackageDescription[] getSubstitutedExports() {
251 		LazyData currentData = loadLazyData();
252 		synchronized (this.monitor) {
253 			if (currentData.substitutedExports == null)
254 				return EMPTY_EXPORTS;
255 			return currentData.substitutedExports;
256 		}
257 	}
258 
getResolvedRequires()259 	public BundleDescription[] getResolvedRequires() {
260 		LazyData currentData = loadLazyData();
261 		synchronized (this.monitor) {
262 			if (currentData.resolvedRequires == null)
263 				return EMPTY_BUNDLEDESCS;
264 			return currentData.resolvedRequires;
265 		}
266 	}
267 
getResolvedImports()268 	public ExportPackageDescription[] getResolvedImports() {
269 		LazyData currentData = loadLazyData();
270 		synchronized (this.monitor) {
271 			if (currentData.resolvedImports == null)
272 				return EMPTY_EXPORTS;
273 			return currentData.resolvedImports;
274 		}
275 	}
276 
getResolvedGenericRequires()277 	public GenericDescription[] getResolvedGenericRequires() {
278 		LazyData currentData = loadLazyData();
279 		synchronized (this.monitor) {
280 			if (currentData.resolvedCapabilities == null)
281 				return EMPTY_GENERICDESCS;
282 			return currentData.resolvedCapabilities;
283 		}
284 	}
285 
getWires()286 	public Map<String, List<StateWire>> getWires() {
287 		LazyData currentData = loadLazyData();
288 		synchronized (this.monitor) {
289 			if (currentData.stateWires == null) {
290 				currentData.stateWires = new HashMap<>(0);
291 			}
292 			return currentData.stateWires;
293 		}
294 	}
295 
getWiresInternal()296 	Map<String, List<StateWire>> getWiresInternal() {
297 		LazyData currentData = loadLazyData();
298 		synchronized (this.monitor) {
299 			return currentData.stateWires;
300 		}
301 	}
302 
setBundleId(long bundleId)303 	protected void setBundleId(long bundleId) {
304 		this.bundleId = bundleId;
305 	}
306 
setSymbolicName(String symbolicName)307 	protected void setSymbolicName(String symbolicName) {
308 		setName(symbolicName);
309 	}
310 
setLocation(String location)311 	protected void setLocation(String location) {
312 		synchronized (this.monitor) {
313 			checkLazyData();
314 			lazyData.location = location;
315 		}
316 	}
317 
setPlatformFilter(String platformFilter)318 	protected void setPlatformFilter(String platformFilter) {
319 		synchronized (this.monitor) {
320 			checkLazyData();
321 			lazyData.platformFilter = platformFilter;
322 		}
323 	}
324 
setExecutionEnvironments(String[] executionEnvironments)325 	protected void setExecutionEnvironments(String[] executionEnvironments) {
326 		synchronized (this.monitor) {
327 			checkLazyData();
328 			lazyData.executionEnvironments = executionEnvironments == null || executionEnvironments.length > 0 ? executionEnvironments : EMPTY_STRING;
329 		}
330 	}
331 
setExportPackages(ExportPackageDescription[] exportPackages)332 	protected void setExportPackages(ExportPackageDescription[] exportPackages) {
333 		synchronized (this.monitor) {
334 			checkLazyData();
335 			lazyData.exportPackages = exportPackages == null || exportPackages.length > 0 ? exportPackages : EMPTY_EXPORTS;
336 			if (exportPackages != null) {
337 				for (ExportPackageDescription exportPackage : exportPackages) {
338 					((ExportPackageDescriptionImpl) exportPackage).setExporter(this);
339 				}
340 			}
341 		}
342 	}
343 
setImportPackages(ImportPackageSpecification[] importPackages)344 	protected void setImportPackages(ImportPackageSpecification[] importPackages) {
345 		synchronized (this.monitor) {
346 			checkLazyData();
347 			lazyData.importPackages = importPackages == null || importPackages.length > 0 ? importPackages : EMPTY_IMPORTS;
348 			if (importPackages != null) {
349 				for (ImportPackageSpecification importPackage : importPackages) {
350 					((ImportPackageSpecificationImpl) importPackage).setBundle(this);
351 					if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(importPackage.getDirective(Constants.RESOLUTION_DIRECTIVE))) {
352 						stateBits |= HAS_DYNAMICIMPORT;
353 					}
354 				}
355 			}
356 		}
357 	}
358 
setRequiredBundles(BundleSpecification[] requiredBundles)359 	protected void setRequiredBundles(BundleSpecification[] requiredBundles) {
360 		synchronized (this.monitor) {
361 			checkLazyData();
362 			lazyData.requiredBundles = requiredBundles == null || requiredBundles.length > 0 ? requiredBundles : EMPTY_BUNDLESPECS;
363 			if (requiredBundles != null)
364 				for (BundleSpecification requiredBundle : requiredBundles) {
365 					((VersionConstraintImpl) requiredBundle).setBundle(this);
366 				}
367 		}
368 	}
369 
setGenericCapabilities(GenericDescription[] genericCapabilities)370 	protected void setGenericCapabilities(GenericDescription[] genericCapabilities) {
371 		synchronized (this.monitor) {
372 			checkLazyData();
373 			lazyData.genericCapabilities = genericCapabilities == null || genericCapabilities.length > 0 ? genericCapabilities : EMPTY_GENERICDESCS;
374 			if (genericCapabilities != null)
375 				for (GenericDescription genericCapability : genericCapabilities) {
376 					((GenericDescriptionImpl) genericCapability).setSupplier(this);
377 				}
378 		}
379 	}
380 
setGenericRequires(GenericSpecification[] genericRequires)381 	protected void setGenericRequires(GenericSpecification[] genericRequires) {
382 		synchronized (this.monitor) {
383 			checkLazyData();
384 			lazyData.genericRequires = genericRequires == null || genericRequires.length > 0 ? genericRequires : EMPTY_GENERICSPECS;
385 			if (genericRequires != null)
386 				for (GenericSpecification genericRequire : genericRequires) {
387 					((VersionConstraintImpl) genericRequire).setBundle(this);
388 				}
389 		}
390 	}
391 
setNativeCodeSpecification(NativeCodeSpecification nativeCode)392 	protected void setNativeCodeSpecification(NativeCodeSpecification nativeCode) {
393 		synchronized (this.monitor) {
394 			checkLazyData();
395 			lazyData.nativeCode = nativeCode;
396 			if (nativeCode != null) {
397 				((NativeCodeSpecificationImpl) nativeCode).setBundle(this);
398 				NativeCodeDescription[] suppliers = nativeCode.getPossibleSuppliers();
399 				if (suppliers != null)
400 					for (NativeCodeDescription supplier : suppliers) {
401 						((NativeCodeDescriptionImpl) supplier).setSupplier(this);
402 					}
403 			}
404 		}
405 	}
406 
getStateBits()407 	protected int getStateBits() {
408 		return stateBits;
409 	}
410 
setStateBit(int stateBit, boolean on)411 	protected void setStateBit(int stateBit, boolean on) {
412 		synchronized (this.monitor) {
413 			if (on) {
414 				stateBits |= stateBit;
415 			} else {
416 				stateBits &= ~stateBit;
417 				if (stateBit == RESOLVED) {
418 					if (bundleWiring != null)
419 						bundleWiring.invalidate();
420 					bundleWiring = null;
421 				}
422 			}
423 		}
424 	}
425 
setContainingState(State value)426 	protected void setContainingState(State value) {
427 		synchronized (this.monitor) {
428 			containingState = (StateImpl) value;
429 			if (containingState != null && containingState.getReader() != null) {
430 				if (containingState.getReader().isLazyLoaded())
431 					stateBits |= LAZY_LOADED;
432 				else
433 					stateBits &= ~LAZY_LOADED;
434 			} else {
435 				stateBits &= ~LAZY_LOADED;
436 			}
437 		}
438 	}
439 
setHost(HostSpecification host)440 	protected void setHost(HostSpecification host) {
441 		synchronized (this.monitor) {
442 			this.host = host;
443 			if (host != null) {
444 				((VersionConstraintImpl) host).setBundle(this);
445 			}
446 		}
447 	}
448 
setLazyLoaded(boolean lazyLoad)449 	protected void setLazyLoaded(boolean lazyLoad) {
450 		loadLazyData();
451 		synchronized (this.monitor) {
452 			if (lazyLoad)
453 				stateBits |= LAZY_LOADED;
454 			else
455 				stateBits &= ~LAZY_LOADED;
456 		}
457 	}
458 
setSelectedExports(ExportPackageDescription[] selectedExports)459 	protected void setSelectedExports(ExportPackageDescription[] selectedExports) {
460 		synchronized (this.monitor) {
461 			checkLazyData();
462 			lazyData.selectedExports = selectedExports == null || selectedExports.length > 0 ? selectedExports : EMPTY_EXPORTS;
463 			if (selectedExports != null) {
464 				for (ExportPackageDescription selectedExport : selectedExports) {
465 					((ExportPackageDescriptionImpl) selectedExport).setExporter(this);
466 				}
467 			}
468 		}
469 	}
470 
setSelectedCapabilities(GenericDescription[] selectedCapabilities)471 	protected void setSelectedCapabilities(GenericDescription[] selectedCapabilities) {
472 		synchronized (this.monitor) {
473 			checkLazyData();
474 			lazyData.selectedCapabilities = selectedCapabilities == null || selectedCapabilities.length > 0 ? selectedCapabilities : EMPTY_GENERICDESCS;
475 			if (selectedCapabilities != null) {
476 				for (GenericDescription capability : selectedCapabilities) {
477 					((GenericDescriptionImpl) capability).setSupplier(this);
478 				}
479 			}
480 		}
481 	}
482 
setSubstitutedExports(ExportPackageDescription[] substitutedExports)483 	protected void setSubstitutedExports(ExportPackageDescription[] substitutedExports) {
484 		synchronized (this.monitor) {
485 			checkLazyData();
486 			lazyData.substitutedExports = substitutedExports != null && substitutedExports.length > 0 ? substitutedExports : EMPTY_EXPORTS;
487 		}
488 	}
489 
setResolvedImports(ExportPackageDescription[] resolvedImports)490 	protected void setResolvedImports(ExportPackageDescription[] resolvedImports) {
491 		synchronized (this.monitor) {
492 			checkLazyData();
493 			lazyData.resolvedImports = resolvedImports == null || resolvedImports.length > 0 ? resolvedImports : EMPTY_EXPORTS;
494 		}
495 	}
496 
setResolvedRequires(BundleDescription[] resolvedRequires)497 	protected void setResolvedRequires(BundleDescription[] resolvedRequires) {
498 		synchronized (this.monitor) {
499 			checkLazyData();
500 			lazyData.resolvedRequires = resolvedRequires == null || resolvedRequires.length > 0 ? resolvedRequires : EMPTY_BUNDLEDESCS;
501 		}
502 	}
503 
setResolvedCapabilities(GenericDescription[] resolvedCapabilities)504 	protected void setResolvedCapabilities(GenericDescription[] resolvedCapabilities) {
505 		synchronized (this.monitor) {
506 			checkLazyData();
507 			lazyData.resolvedCapabilities = resolvedCapabilities == null || resolvedCapabilities.length > 0 ? resolvedCapabilities : EMPTY_GENERICDESCS;
508 		}
509 	}
510 
setStateWires(Map<String, List<StateWire>> stateWires)511 	protected void setStateWires(Map<String, List<StateWire>> stateWires) {
512 		synchronized (this.monitor) {
513 			checkLazyData();
514 			lazyData.stateWires = stateWires;
515 		}
516 	}
517 
clearAddedDynamicImportPackages()518 	void clearAddedDynamicImportPackages() {
519 		synchronized (this.monitor) {
520 			checkLazyData();
521 			lazyData.addedDynamicImports = null;
522 		}
523 	}
524 
525 	@Override
toString()526 	public String toString() {
527 		if (getSymbolicName() == null)
528 			return "[" + getBundleId() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
529 		return getSymbolicName() + "_" + getVersion(); //$NON-NLS-1$
530 	}
531 
getKey()532 	public Object getKey() {
533 		return new Long(bundleId);
534 	}
535 
compare(KeyedElement other)536 	public boolean compare(KeyedElement other) {
537 		if (!(other instanceof BundleDescriptionImpl))
538 			return false;
539 		BundleDescriptionImpl otherBundleDescription = (BundleDescriptionImpl) other;
540 		return bundleId == otherBundleDescription.bundleId;
541 	}
542 
getKeyHashCode()543 	public int getKeyHashCode() {
544 		return (int) (bundleId ^ (bundleId >>> 32));
545 	}
546 
547 	/* TODO Determine if we need more than just Object ID type of hashcode.
548 	 public int hashCode() {
549 	 if (getSymbolicName() == null)
550 	 return (int) (bundleId % Integer.MAX_VALUE);
551 	 return (int) ((bundleId * (getSymbolicName().hashCode())) % Integer.MAX_VALUE);
552 	 }
553 	 */
554 
removeDependencies()555 	protected void removeDependencies() {
556 		synchronized (this.monitor) {
557 			if (dependencies == null)
558 				return;
559 			Iterator<BundleDescription> iter = dependencies.iterator();
560 			while (iter.hasNext()) {
561 				((BundleDescriptionImpl) iter.next()).removeDependent(this);
562 			}
563 			dependencies = null;
564 		}
565 	}
566 
addDependencies(BaseDescription[] newDependencies, boolean checkDups)567 	protected void addDependencies(BaseDescription[] newDependencies, boolean checkDups) {
568 		synchronized (this.monitor) {
569 			if (newDependencies == null)
570 				return;
571 			if (!checkDups && dependencies == null)
572 				dependencies = new ArrayList<>(newDependencies.length);
573 			for (BaseDescription newDependency : newDependencies) {
574 				addDependency((BaseDescriptionImpl) newDependency, checkDups);
575 			}
576 		}
577 	}
578 
addDependency(BaseDescriptionImpl dependency, boolean checkDups)579 	protected void addDependency(BaseDescriptionImpl dependency, boolean checkDups) {
580 		synchronized (this.monitor) {
581 			BundleDescriptionImpl bundle = (BundleDescriptionImpl) dependency.getSupplier();
582 			if (bundle == this)
583 				return;
584 			if (dependencies == null)
585 				dependencies = new ArrayList<>(10);
586 			if (!checkDups || !dependencies.contains(bundle)) {
587 				bundle.addDependent(this);
588 				dependencies.add(bundle);
589 			}
590 		}
591 	}
592 
593 	/*
594 	 * Gets all the bundle dependencies as a result of import-package or require-bundle.
595 	 * Self and fragment bundles are removed.
596 	 */
getBundleDependencies()597 	List<BundleDescription> getBundleDependencies() {
598 		synchronized (this.monitor) {
599 			if (dependencies == null)
600 				return new ArrayList<>(0);
601 			ArrayList<BundleDescription> required = new ArrayList<>(dependencies.size());
602 			for (Iterator<BundleDescription> iter = dependencies.iterator(); iter.hasNext();) {
603 				BundleDescription dep = iter.next();
604 				if (dep != this && dep.getHost() == null)
605 					required.add(dep);
606 			}
607 			return required;
608 		}
609 	}
610 
addDependent(BundleDescription dependent)611 	protected void addDependent(BundleDescription dependent) {
612 		synchronized (this.monitor) {
613 			if (dependents == null)
614 				dependents = new ArrayList<>(10);
615 			// no need to check for duplicates here; this is only called in addDepenency which already checks for dups.
616 			dependents.add(dependent);
617 		}
618 	}
619 
removeDependent(BundleDescription dependent)620 	protected void removeDependent(BundleDescription dependent) {
621 		synchronized (this.monitor) {
622 			if (dependents == null)
623 				return;
624 			dependents.remove(dependent);
625 		}
626 	}
627 
getDependents()628 	public BundleDescription[] getDependents() {
629 		synchronized (this.monitor) {
630 			if (dependents == null)
631 				return EMPTY_BUNDLEDESCS;
632 			return dependents.toArray(new BundleDescription[dependents.size()]);
633 		}
634 	}
635 
hasDependents()636 	boolean hasDependents() {
637 		synchronized (this.monitor) {
638 			return dependents == null ? false : dependents.size() > 0;
639 		}
640 	}
641 
setFullyLoaded(boolean fullyLoaded)642 	void setFullyLoaded(boolean fullyLoaded) {
643 		synchronized (this.monitor) {
644 			if (fullyLoaded) {
645 				stateBits |= FULLY_LOADED;
646 			} else {
647 				stateBits &= ~FULLY_LOADED;
648 			}
649 		}
650 	}
651 
isFullyLoaded()652 	boolean isFullyLoaded() {
653 		return (stateBits & FULLY_LOADED) != 0;
654 	}
655 
setLazyDataOffset(int lazyDataOffset)656 	void setLazyDataOffset(int lazyDataOffset) {
657 		this.lazyDataOffset = lazyDataOffset;
658 	}
659 
getLazyDataOffset()660 	int getLazyDataOffset() {
661 		return this.lazyDataOffset;
662 	}
663 
setLazyDataSize(int lazyDataSize)664 	void setLazyDataSize(int lazyDataSize) {
665 		this.lazyDataSize = lazyDataSize;
666 	}
667 
getLazyDataSize()668 	int getLazyDataSize() {
669 		return this.lazyDataSize;
670 	}
671 
672 	// DO NOT call while holding this.monitor
loadLazyData()673 	private LazyData loadLazyData() {
674 		// TODO add back if ee min 1.2 adds holdsLock method
675 		//if (Thread.holdsLock(this.monitor)) {
676 		//	throw new IllegalStateException("Should not call fullyLoad() holding monitor."); //$NON-NLS-1$
677 		//}
678 		if ((stateBits & LAZY_LOADED) == 0)
679 			return this.lazyData;
680 
681 		StateImpl currentState = (StateImpl) getContainingState();
682 		StateReader reader = currentState == null ? null : currentState.getReader();
683 		if (reader == null)
684 			throw new IllegalStateException("No valid reader for the bundle description"); //$NON-NLS-1$
685 
686 		synchronized (currentState.monitor) {
687 			if (isFullyLoaded()) {
688 				reader.setAccessedFlag(true); // set reader accessed flag
689 				return this.lazyData;
690 			}
691 			try {
692 				reader.fullyLoad(this);
693 				return this.lazyData;
694 			} catch (IOException e) {
695 				throw new RuntimeException(e.getMessage(), e); // TODO not sure what to do here!!
696 			}
697 		}
698 	}
699 
addDynamicResolvedImport(ExportPackageDescriptionImpl result)700 	void addDynamicResolvedImport(ExportPackageDescriptionImpl result) {
701 		synchronized (this.monitor) {
702 			// mark the dependency
703 			addDependency(result, true);
704 			// add the export to the list of the resolvedImports
705 			checkLazyData();
706 			if (lazyData.resolvedImports == null) {
707 				lazyData.resolvedImports = new ExportPackageDescription[] {result};
708 				return;
709 			}
710 			ExportPackageDescription[] newImports = new ExportPackageDescription[lazyData.resolvedImports.length + 1];
711 			System.arraycopy(lazyData.resolvedImports, 0, newImports, 0, lazyData.resolvedImports.length);
712 			newImports[newImports.length - 1] = result;
713 			lazyData.resolvedImports = newImports;
714 		}
715 	}
716 
addDynamicImportPackages(ImportPackageSpecification[] dynamicImport)717 	void addDynamicImportPackages(ImportPackageSpecification[] dynamicImport) {
718 		LazyData currentData = loadLazyData();
719 		synchronized (this.monitor) {
720 			if (currentData.addedDynamicImports == null)
721 				currentData.addedDynamicImports = new ArrayList<>();
722 			for (ImportPackageSpecification addImport : dynamicImport) {
723 				if (!ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(addImport.getDirective(Constants.RESOLUTION_DIRECTIVE)))
724 					throw new IllegalArgumentException("Import must be a dynamic import."); //$NON-NLS-1$
725 			}
726 			adding: for (ImportPackageSpecification addImport : dynamicImport) {
727 				for (ImportPackageSpecification currentImport : currentData.addedDynamicImports) {
728 					if (equalImports(addImport, currentImport))
729 						continue adding;
730 				}
731 				((ImportPackageSpecificationImpl) addImport).setBundle(this);
732 				currentData.addedDynamicImports.add(addImport);
733 			}
734 		}
735 	}
736 
equalImports(ImportPackageSpecification addImport, ImportPackageSpecification currentImport)737 	private boolean equalImports(ImportPackageSpecification addImport, ImportPackageSpecification currentImport) {
738 		if (!isEqual(addImport.getName(), currentImport.getName()))
739 			return false;
740 		if (!isEqual(addImport.getVersionRange(), currentImport.getVersionRange()))
741 			return false;
742 		if (!isEqual(addImport.getBundleSymbolicName(), currentImport.getBundleSymbolicName()))
743 			return false;
744 		if (!isEqual(addImport.getBundleVersionRange(), currentImport.getBundleVersionRange()))
745 			return false;
746 		return isEqual(addImport.getAttributes(), currentImport.getAttributes());
747 	}
748 
isEqual(Object o1, Object o2)749 	private boolean isEqual(Object o1, Object o2) {
750 		return (o1 == null) ? o2 == null : o1.equals(o2);
751 	}
752 
unload()753 	void unload() {
754 		StateImpl currentState = (StateImpl) getContainingState();
755 		StateReader reader = currentState == null ? null : currentState.getReader();
756 		if (reader == null)
757 			throw new IllegalStateException("BundleDescription does not belong to a reader."); //$NON-NLS-1$
758 		synchronized (currentState.monitor) {
759 			if ((stateBits & LAZY_LOADED) == 0)
760 				return;
761 			if (!isFullyLoaded())
762 				return;
763 			synchronized (this.monitor) {
764 				setFullyLoaded(false);
765 				lazyData = null;
766 			}
767 		}
768 	}
769 
setDynamicStamps(Map<String, Long> dynamicStamps)770 	void setDynamicStamps(Map<String, Long> dynamicStamps) {
771 		synchronized (this.monitor) {
772 			checkLazyData();
773 			lazyData.dynamicStamps = dynamicStamps;
774 		}
775 	}
776 
setDynamicStamp(String requestedPackage, Long timestamp)777 	void setDynamicStamp(String requestedPackage, Long timestamp) {
778 		synchronized (this.monitor) {
779 			checkLazyData();
780 			if (lazyData.dynamicStamps == null) {
781 				if (timestamp == null)
782 					return;
783 				lazyData.dynamicStamps = new HashMap<>();
784 			}
785 			if (timestamp == null)
786 				lazyData.dynamicStamps.remove(requestedPackage);
787 			else
788 				lazyData.dynamicStamps.put(requestedPackage, timestamp);
789 		}
790 	}
791 
getDynamicStamp(String requestedPackage)792 	long getDynamicStamp(String requestedPackage) {
793 		LazyData currentData = loadLazyData();
794 		synchronized (this.monitor) {
795 			Long stamp = currentData.dynamicStamps == null ? null : (Long) currentData.dynamicStamps.get(requestedPackage);
796 			return stamp == null ? 0 : stamp.longValue();
797 		}
798 	}
799 
getDynamicStamps()800 	Map<String, Long> getDynamicStamps() {
801 		LazyData currentData = loadLazyData();
802 		synchronized (this.monitor) {
803 			return currentData.dynamicStamps;
804 		}
805 	}
806 
setEquinoxEE(int equinox_ee)807 	public void setEquinoxEE(int equinox_ee) {
808 		this.equinox_ee = equinox_ee;
809 	}
810 
getEquinoxEE()811 	public int getEquinoxEE() {
812 		return equinox_ee;
813 	}
814 
checkLazyData()815 	private void checkLazyData() {
816 		if (lazyData == null)
817 			lazyData = new LazyData();
818 	}
819 
820 	final class LazyData {
821 		String location;
822 		String platformFilter;
823 
824 		BundleSpecification[] requiredBundles;
825 		ExportPackageDescription[] exportPackages;
826 		ImportPackageSpecification[] importPackages;
827 		GenericDescription[] genericCapabilities;
828 		GenericSpecification[] genericRequires;
829 		NativeCodeSpecification nativeCode;
830 
831 		ExportPackageDescription[] selectedExports;
832 		GenericDescription[] selectedCapabilities;
833 		BundleDescription[] resolvedRequires;
834 		ExportPackageDescription[] resolvedImports;
835 		GenericDescription[] resolvedCapabilities;
836 		ExportPackageDescription[] substitutedExports;
837 		String[] executionEnvironments;
838 
839 		Map<String, Long> dynamicStamps;
840 		Map<String, List<StateWire>> stateWires;
841 		// Note that this is not persisted in the state cache
842 		List<ImportPackageSpecification> addedDynamicImports;
843 	}
844 
getAttributes()845 	public Map<String, Object> getAttributes() {
846 		synchronized (this.monitor) {
847 			return attributes;
848 		}
849 	}
850 
851 	@SuppressWarnings("unchecked")
setAttributes(Map<String, ?> attributes)852 	void setAttributes(Map<String, ?> attributes) {
853 		synchronized (this.monitor) {
854 			this.attributes = (Map<String, Object>) attributes;
855 		}
856 	}
857 
getDirective(String key)858 	Object getDirective(String key) {
859 		synchronized (this.monitor) {
860 			if (Constants.MANDATORY_DIRECTIVE.equals(key))
861 				return mandatory;
862 			if (Constants.SINGLETON_DIRECTIVE.equals(key))
863 				return isSingleton() ? Boolean.TRUE : Boolean.FALSE;
864 			if (Constants.FRAGMENT_ATTACHMENT_DIRECTIVE.equals(key)) {
865 				if (!attachFragments())
866 					return Constants.FRAGMENT_ATTACHMENT_NEVER;
867 				if (dynamicFragments())
868 					return Constants.FRAGMENT_ATTACHMENT_ALWAYS;
869 				return Constants.FRAGMENT_ATTACHMENT_RESOLVETIME;
870 			}
871 		}
872 		return null;
873 	}
874 
setDirective(String key, Object value)875 	void setDirective(String key, Object value) {
876 		// only pay attention to mandatory directive for now; others are set with setState method
877 		if (Constants.MANDATORY_DIRECTIVE.equals(key))
878 			mandatory = (String[]) value;
879 	}
880 
881 	@SuppressWarnings("unchecked")
setArbitraryDirectives(Map<String, ?> directives)882 	void setArbitraryDirectives(Map<String, ?> directives) {
883 		synchronized (this.monitor) {
884 			this.arbitraryDirectives = (Map<String, String>) directives;
885 		}
886 	}
887 
getArbitraryDirectives()888 	Map<String, String> getArbitraryDirectives() {
889 		synchronized (this.monitor) {
890 			return arbitraryDirectives;
891 		}
892 	}
893 
getDeclaredDirectives()894 	public Map<String, String> getDeclaredDirectives() {
895 		Map<String, String> result = new HashMap<>(2);
896 		Map<String, String> arbitrary = getArbitraryDirectives();
897 		if (arbitrary != null)
898 			result.putAll(arbitrary);
899 		if (!attachFragments()) {
900 			result.put(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_NEVER);
901 		} else {
902 			if (dynamicFragments())
903 				result.put(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_ALWAYS);
904 			else
905 				result.put(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_RESOLVETIME);
906 		}
907 		if (isSingleton())
908 			result.put(Constants.SINGLETON_DIRECTIVE, Boolean.TRUE.toString());
909 		String[] mandatoryDirective = (String[]) getDirective(Constants.MANDATORY_DIRECTIVE);
910 		if (mandatoryDirective != null)
911 			result.put(Constants.MANDATORY_DIRECTIVE, ExportPackageDescriptionImpl.toString(mandatoryDirective));
912 		return Collections.unmodifiableMap(result);
913 	}
914 
getDeclaredAttributes()915 	public Map<String, Object> getDeclaredAttributes() {
916 		Map<String, Object> result = new HashMap<>(1);
917 		synchronized (this.monitor) {
918 			if (attributes != null)
919 				result.putAll(attributes);
920 		}
921 		result.put(BundleRevision.BUNDLE_NAMESPACE, getName());
922 		result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, getVersion());
923 		return Collections.unmodifiableMap(result);
924 	}
925 
getDeclaredRequirements(String namespace)926 	public List<BundleRequirement> getDeclaredRequirements(String namespace) {
927 		List<BundleRequirement> result = new ArrayList<>();
928 		if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) {
929 			BundleSpecification[] requires = getRequiredBundles();
930 			for (BundleSpecification require : requires) {
931 				result.add(require.getRequirement());
932 			}
933 		}
934 		if (host != null && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) {
935 			result.add(host.getRequirement());
936 		}
937 		if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) {
938 			ImportPackageSpecification[] imports = getImportPackages();
939 			for (ImportPackageSpecification importPkg : imports)
940 				result.add(importPkg.getRequirement());
941 		}
942 		GenericSpecification[] genericSpecifications = getGenericRequires();
943 		for (GenericSpecification requirement : genericSpecifications) {
944 			if (namespace == null || namespace.equals(requirement.getType()))
945 				result.add(requirement.getRequirement());
946 		}
947 		return Collections.unmodifiableList(result);
948 	}
949 
getDeclaredCapabilities(String namespace)950 	public List<BundleCapability> getDeclaredCapabilities(String namespace) {
951 		List<BundleCapability> result = new ArrayList<>();
952 		if (host == null) {
953 			if (getSymbolicName() != null) {
954 				if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) {
955 					result.add(BundleDescriptionImpl.this.getCapability());
956 				}
957 				if (attachFragments() && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) {
958 					result.add(BundleDescriptionImpl.this.getCapability(BundleRevision.HOST_NAMESPACE));
959 				}
960 			}
961 
962 		} else {
963 			// may need to have a osgi.wiring.fragment capability
964 		}
965 		if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) {
966 			ExportPackageDescription[] exports = getExportPackages();
967 			for (ExportPackageDescription exportPkg : exports)
968 				result.add(exportPkg.getCapability());
969 		}
970 		GenericDescription[] genericCapabilities = getGenericCapabilities();
971 		for (GenericDescription capabilitiy : genericCapabilities) {
972 			if (namespace == null || namespace.equals(capabilitiy.getType()))
973 				result.add(capabilitiy.getCapability());
974 		}
975 		return Collections.unmodifiableList(result);
976 	}
977 
getTypes()978 	public int getTypes() {
979 		return getHost() != null ? BundleRevision.TYPE_FRAGMENT : 0;
980 	}
981 
getBundle()982 	public Bundle getBundle() {
983 		Object ref = getUserObject();
984 		if (ref instanceof BundleReference)
985 			return ((BundleReference) ref).getBundle();
986 		return null;
987 	}
988 
989 	@Override
getInternalNameSpace()990 	String getInternalNameSpace() {
991 		return BundleRevision.BUNDLE_NAMESPACE;
992 	}
993 
getWiring()994 	public BundleWiring getWiring() {
995 		synchronized (this.monitor) {
996 			if (bundleWiring != null || !isResolved())
997 				return bundleWiring;
998 			return bundleWiring = new DescriptionWiring();
999 		}
1000 	}
1001 
1002 	static class BundleWireImpl implements BundleWire {
1003 		private final BundleCapability capability;
1004 		private final BundleWiring provider;
1005 		private final BundleRequirement requirement;
1006 		private final BundleWiring requirer;
1007 
BundleWireImpl(StateWire wire)1008 		public BundleWireImpl(StateWire wire) {
1009 			VersionConstraint declaredRequirement = wire.getDeclaredRequirement();
1010 			if (declaredRequirement instanceof HostSpecification)
1011 				this.capability = ((BaseDescriptionImpl) wire.getDeclaredCapability()).getCapability(BundleRevision.HOST_NAMESPACE);
1012 			else
1013 				this.capability = wire.getDeclaredCapability().getCapability();
1014 			this.provider = wire.getCapabilityHost().getWiring();
1015 			this.requirement = declaredRequirement.getRequirement();
1016 			this.requirer = wire.getRequirementHost().getWiring();
1017 		}
1018 
getCapability()1019 		public BundleCapability getCapability() {
1020 			return capability;
1021 		}
1022 
getRequirement()1023 		public BundleRequirement getRequirement() {
1024 			return requirement;
1025 		}
1026 
getProviderWiring()1027 		public BundleWiring getProviderWiring() {
1028 			return provider;
1029 		}
1030 
getRequirerWiring()1031 		public BundleWiring getRequirerWiring() {
1032 			return requirer;
1033 		}
1034 
1035 		@Override
hashCode()1036 		public int hashCode() {
1037 			int hashcode = 31 + capability.hashCode();
1038 			hashcode = hashcode * 31 + requirement.hashCode();
1039 			hashcode = hashcode * 31 + provider.hashCode();
1040 			hashcode = hashcode * 31 + requirer.hashCode();
1041 			return hashcode;
1042 		}
1043 
1044 		@Override
equals(Object obj)1045 		public boolean equals(Object obj) {
1046 			if (!(obj instanceof BundleWireImpl))
1047 				return false;
1048 			BundleWireImpl other = (BundleWireImpl) obj;
1049 			return capability.equals(other.getCapability()) && requirement.equals(other.getRequirement()) && provider.equals(other.getProviderWiring()) && requirer.equals(other.getRequirerWiring());
1050 		}
1051 
1052 		@Override
toString()1053 		public String toString() {
1054 			return getRequirement() + " -> " + getCapability(); //$NON-NLS-1$
1055 		}
1056 
getProvider()1057 		public BundleRevision getProvider() {
1058 			return provider.getRevision();
1059 		}
1060 
getRequirer()1061 		public BundleRevision getRequirer() {
1062 			return requirer.getRevision();
1063 		}
1064 	}
1065 
1066 	/**
1067 	 * Coerce the generic type of a list from List<BundleWire>
1068 	 * to List<Wire>
1069 	 * @param l List to be coerced.
1070 	 * @return l coerced to List<Wire>
1071 	 */
1072 	@SuppressWarnings("unchecked")
asListWire(List<? extends Wire> l)1073 	static List<Wire> asListWire(List<? extends Wire> l) {
1074 		return (List<Wire>) l;
1075 	}
1076 
1077 	/**
1078 	 * Coerce the generic type of a list from List<BundleCapability>
1079 	 * to List<Capability>
1080 	 * @param l List to be coerced.
1081 	 * @return l coerced to List<Capability>
1082 	 */
1083 	@SuppressWarnings("unchecked")
asListCapability(List<? extends Capability> l)1084 	static List<Capability> asListCapability(List<? extends Capability> l) {
1085 		return (List<Capability>) l;
1086 	}
1087 
1088 	/**
1089 	 * Coerce the generic type of a list from List<BundleRequirement>
1090 	 * to List<Requirement>
1091 	 * @param l List to be coerced.
1092 	 * @return l coerced to List<Requirement>
1093 	 */
1094 	@SuppressWarnings("unchecked")
asListRequirement(List<? extends Requirement> l)1095 	static List<Requirement> asListRequirement(List<? extends Requirement> l) {
1096 		return (List<Requirement>) l;
1097 	}
1098 
1099 	// Note that description wiring are identity equality based
1100 	class DescriptionWiring implements BundleWiring {
1101 		private volatile boolean valid = true;
1102 
getBundle()1103 		public Bundle getBundle() {
1104 			return BundleDescriptionImpl.this.getBundle();
1105 		}
1106 
isInUse()1107 		public boolean isInUse() {
1108 			return valid && (isCurrent() || BundleDescriptionImpl.this.hasDependents());
1109 		}
1110 
invalidate()1111 		void invalidate() {
1112 			valid = false;
1113 		}
1114 
isCurrent()1115 		public boolean isCurrent() {
1116 			return valid && !BundleDescriptionImpl.this.isRemovalPending();
1117 		}
1118 
getCapabilities(String namespace)1119 		public List<BundleCapability> getCapabilities(String namespace) {
1120 			if (!isInUse())
1121 				return null;
1122 			List<BundleCapability> result = new ArrayList<>();
1123 			GenericDescription[] genericCapabilities = getSelectedGenericCapabilities();
1124 			for (GenericDescription capabilitiy : genericCapabilities) {
1125 				if (namespace == null || namespace.equals(capabilitiy.getType()))
1126 					result.add(capabilitiy.getCapability());
1127 			}
1128 			if (host != null)
1129 				return result;
1130 			if (getSymbolicName() != null) {
1131 				if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) {
1132 					result.add(BundleDescriptionImpl.this.getCapability());
1133 				}
1134 				if (attachFragments() && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) {
1135 					result.add(BundleDescriptionImpl.this.getCapability(BundleRevision.HOST_NAMESPACE));
1136 				}
1137 			}
1138 			if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) {
1139 				ExportPackageDescription[] exports = getSelectedExports();
1140 				for (ExportPackageDescription exportPkg : exports)
1141 					result.add(exportPkg.getCapability());
1142 			}
1143 			return result;
1144 		}
1145 
getResourceCapabilities(String namespace)1146 		public List<Capability> getResourceCapabilities(String namespace) {
1147 			return asListCapability(getCapabilities(namespace));
1148 		}
1149 
getRequirements(String namespace)1150 		public List<BundleRequirement> getRequirements(String namespace) {
1151 			List<BundleWire> requiredWires = getRequiredWires(namespace);
1152 			if (requiredWires == null)
1153 				// happens if not in use
1154 				return null;
1155 			List<BundleRequirement> requirements = new ArrayList<>(requiredWires.size());
1156 			for (BundleWire wire : requiredWires) {
1157 				if (!requirements.contains(wire.getRequirement()))
1158 					requirements.add(wire.getRequirement());
1159 			}
1160 			// get dynamic imports
1161 			if (getHost() == null && (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace))) {
1162 				// TODO need to handle fragments that add dynamic imports
1163 				if (hasDynamicImports()) {
1164 					ImportPackageSpecification[] imports = getImportPackages();
1165 					for (ImportPackageSpecification impPackage : imports) {
1166 						if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(impPackage.getDirective(Constants.RESOLUTION_DIRECTIVE))) {
1167 							BundleRequirement req = impPackage.getRequirement();
1168 							if (!requirements.contains(req))
1169 								requirements.add(req);
1170 						}
1171 					}
1172 				}
1173 				ImportPackageSpecification[] addedDynamic = getAddedDynamicImportPackages();
1174 				for (ImportPackageSpecification dynamicImport : addedDynamic) {
1175 					BundleRequirement req = dynamicImport.getRequirement();
1176 					if (!requirements.contains(req))
1177 						requirements.add(req);
1178 				}
1179 			}
1180 			return requirements;
1181 		}
1182 
getResourceRequirements(String namespace)1183 		public List<Requirement> getResourceRequirements(String namespace) {
1184 			return asListRequirement(getRequirements(namespace));
1185 		}
1186 
getProvidedWires(String namespace)1187 		public List<BundleWire> getProvidedWires(String namespace) {
1188 			if (!isInUse())
1189 				return null;
1190 			BundleDescription[] dependentBundles = getDependents();
1191 			List<BundleWire> unorderedResult = new ArrayList<>();
1192 			for (BundleDescription dependent : dependentBundles) {
1193 				List<BundleWire> dependentWires = dependent.getWiring().getRequiredWires(namespace);
1194 				if (dependentWires != null)
1195 					for (BundleWire bundleWire : dependentWires) {
1196 						if (bundleWire.getProviderWiring() == this)
1197 							unorderedResult.add(bundleWire);
1198 					}
1199 			}
1200 			List<BundleWire> orderedResult = new ArrayList<>(unorderedResult.size());
1201 			List<BundleCapability> capabilities = getCapabilities(namespace);
1202 			for (BundleCapability capability : capabilities) {
1203 				for (Iterator<BundleWire> wires = unorderedResult.iterator(); wires.hasNext();) {
1204 					BundleWire wire = wires.next();
1205 					if (wire.getCapability().equals(capability)) {
1206 						wires.remove();
1207 						orderedResult.add(wire);
1208 					}
1209 				}
1210 			}
1211 			return orderedResult;
1212 		}
1213 
getProvidedResourceWires(String namespace)1214 		public List<Wire> getProvidedResourceWires(String namespace) {
1215 			return asListWire(getProvidedWires(namespace));
1216 		}
1217 
getRequiredWires(String namespace)1218 		public List<BundleWire> getRequiredWires(String namespace) {
1219 			if (!isInUse())
1220 				return null;
1221 			List<BundleWire> result = Collections.<BundleWire> emptyList();
1222 			Map<String, List<StateWire>> wireMap = getWires();
1223 			if (namespace == null) {
1224 				result = new ArrayList<>();
1225 				for (List<StateWire> wires : wireMap.values()) {
1226 					for (StateWire wire : wires) {
1227 						result.add(new BundleWireImpl(wire));
1228 					}
1229 				}
1230 				return result;
1231 			}
1232 			List<StateWire> wires = wireMap.get(namespace);
1233 			if (wires == null)
1234 				return result;
1235 			result = new ArrayList<>(wires.size());
1236 			for (StateWire wire : wires) {
1237 				result.add(new BundleWireImpl(wire));
1238 			}
1239 			return result;
1240 		}
1241 
getRequiredResourceWires(String namespace)1242 		public List<Wire> getRequiredResourceWires(String namespace) {
1243 			return asListWire(getRequiredWires(namespace));
1244 		}
1245 
getRevision()1246 		public BundleRevision getRevision() {
1247 			return BundleDescriptionImpl.this;
1248 		}
1249 
getResource()1250 		public BundleRevision getResource() {
1251 			return getRevision();
1252 		}
1253 
getClassLoader()1254 		public ClassLoader getClassLoader() {
1255 			throw new UnsupportedOperationException();
1256 		}
1257 
findEntries(String path, String filePattern, int options)1258 		public List<URL> findEntries(String path, String filePattern, int options) {
1259 			return null;
1260 		}
1261 
listResources(String path, String filePattern, int options)1262 		public Collection<String> listResources(String path, String filePattern, int options) {
1263 			return null;
1264 		}
1265 
1266 		@Override
toString()1267 		public String toString() {
1268 			return BundleDescriptionImpl.this.toString();
1269 		}
1270 	}
1271 
getCapabilities(String namespace)1272 	public List<Capability> getCapabilities(String namespace) {
1273 		return asListCapability(getDeclaredCapabilities(namespace));
1274 	}
1275 
getRequirements(String namespace)1276 	public List<Requirement> getRequirements(String namespace) {
1277 		return asListRequirement(getDeclaredRequirements(namespace));
1278 	}
1279 }
1280