1 11 package org.eclipse.osgi.internal.resolver; 12 13 import java.util.*; 14 15 import org.eclipse.osgi.framework.internal.core.Constants; 16 import org.eclipse.osgi.service.resolver.*; 17 18 23 public class StateHelperImpl implements StateHelper { 24 private static StateHelper instance = new StateHelperImpl(); 25 26 29 public BundleDescription[] getDependentBundles(BundleDescription[] bundles) { 30 if (bundles == null || bundles.length == 0) 31 return new BundleDescription[0]; 32 33 Set reachable = new HashSet(bundles.length); 34 for (int i = 0; i < bundles.length; i++) { 35 if (!bundles[i].isResolved()) 36 continue; 37 addDependentBundles(bundles[i], reachable); 38 } 39 return (BundleDescription[]) reachable.toArray(new BundleDescription[reachable.size()]); 40 } 41 42 private void addDependentBundles(BundleDescription bundle, Set reachable) { 43 if (reachable.contains(bundle)) 44 return; 45 reachable.add(bundle); 46 BundleDescription[] dependents = bundle.getDependents(); 47 for (int i = 0; i < dependents.length; i++) 48 addDependentBundles(dependents[i], reachable); 49 } 50 51 public BundleDescription[] getPrerequisites(BundleDescription[] bundles) { 52 if (bundles == null || bundles.length == 0) 53 return new BundleDescription[0]; 54 Set reachable = new HashSet(bundles.length); 55 for (int i = 0; i < bundles.length; i++) 56 addPrerequisites(bundles[i], reachable); 57 return (BundleDescription[]) reachable.toArray(new BundleDescription[reachable.size()]); 58 } 59 60 private void addPrerequisites(BundleDescription bundle, Set reachable) { 61 if (reachable.contains(bundle)) 62 return; 63 reachable.add(bundle); 64 List depList = ((BundleDescriptionImpl) bundle).getBundleDependencies(); 65 BundleDescription[] dependencies = (BundleDescription[]) depList.toArray(new BundleDescription[depList.size()]); 66 for (int i = 0; i < dependencies.length; i++) 67 addPrerequisites(dependencies[i], reachable); 68 } 69 70 private Map getExportedPackageMap(State state) { 71 Map result = new HashMap(11); 72 BundleDescription[] bundles = state.getBundles(); 73 for (int i = 0; i < bundles.length; i++) { 74 ExportPackageDescription[] packages = bundles[i].getExportPackages(); 75 for (int j = 0; j < packages.length; j++) { 76 ExportPackageDescription description = packages[j]; 77 Set exports = (Set) result.get(description.getName()); 78 if (exports == null) { 79 exports = new HashSet(1); 80 result.put(description.getName(), exports); 81 } 82 exports.add(description); 83 } 84 } 85 return result; 86 } 87 88 private Map getGenericsMap(State state, boolean resolved) { 89 Map result = new HashMap(11); 90 BundleDescription[] bundles = state.getBundles(); 91 for (int i = 0; i < bundles.length; i++) { 92 if (resolved && !bundles[i].isResolved()) 93 continue; GenericDescription[] generics = bundles[i].getGenericCapabilities(); 95 for (int j = 0; j < generics.length; j++) { 96 GenericDescription description = generics[j]; 97 Set genericSet = (Set) result.get(description.getName()); 98 if (genericSet == null) { 99 genericSet = new HashSet(1); 100 result.put(description.getName(), genericSet); 101 } 102 genericSet.add(description); 103 } 104 } 105 return result; 106 } 107 108 private VersionConstraint[] getUnsatisfiedLeaves(State state, BundleDescription[] bundles) { 109 Map packages = getExportedPackageMap(state); 110 Map generics = getGenericsMap(state, false); 111 HashSet result = new HashSet(11); 112 for (int i = 0; i < bundles.length; i++) { 113 BundleDescription description = bundles[i]; 114 VersionConstraint[] constraints = getUnsatisfiedConstraints(description); 115 for (int j = 0; j < constraints.length; j++) { 116 VersionConstraint constraint = constraints[j]; 117 boolean satisfied = false; 118 if (constraint instanceof BundleSpecification || constraint instanceof HostSpecification) { 119 BundleDescription[] suppliers = state.getBundles(constraint.getName()); 120 for (int k = 0; k < suppliers.length && !satisfied; k++) 121 satisfied |= constraint.isSatisfiedBy(suppliers[k]); 122 } else if (constraint instanceof ImportPackageSpecification) { 123 Set exports = (Set) packages.get(constraint.getName()); 124 if (exports != null) 125 for (Iterator iter = exports.iterator(); iter.hasNext() && !satisfied;) 126 satisfied |= constraint.isSatisfiedBy((ExportPackageDescription) iter.next()); 127 } else if (constraint instanceof GenericSpecification) { 128 Set genericSet = (Set) generics.get(constraint.getName()); 129 if (genericSet != null) 130 for (Iterator iter = genericSet.iterator(); iter.hasNext() && !satisfied;) 131 satisfied |= constraint.isSatisfiedBy((GenericDescription) iter.next()); 132 } 133 if (!satisfied) 134 result.add(constraint); 135 } 136 } 137 return (VersionConstraint[]) result.toArray(new VersionConstraint[result.size()]); 138 139 } 140 141 public VersionConstraint[] getUnsatisfiedLeaves(BundleDescription[] bundles) { 142 if (bundles.length == 0) 143 return new VersionConstraint[0]; 144 State state = bundles[0].getContainingState(); 145 return getUnsatisfiedLeaves(state, bundles); 146 } 147 148 151 public VersionConstraint[] getUnsatisfiedConstraints(BundleDescription bundle) { 152 State containingState = bundle.getContainingState(); 153 if (containingState == null) 154 throw new IllegalStateException ("Does not belong to a state"); List unsatisfied = new ArrayList(); 157 HostSpecification host = bundle.getHost(); 158 if (host != null) 159 if (!host.isResolved() && !isResolvable(host)) 160 unsatisfied.add(host); 161 BundleSpecification[] requiredBundles = bundle.getRequiredBundles(); 162 for (int i = 0; i < requiredBundles.length; i++) 163 if (!requiredBundles[i].isResolved() && !isResolvable(requiredBundles[i])) 164 unsatisfied.add(requiredBundles[i]); 165 ImportPackageSpecification[] packages = bundle.getImportPackages(); 166 for (int i = 0; i < packages.length; i++) 167 if (!packages[i].isResolved() && !isResolvable(packages[i])) 168 unsatisfied.add(packages[i]); 169 GenericSpecification[] generics = bundle.getGenericRequires(); 170 for (int i = 0; i < generics.length; i++) 171 if (!generics[i].isResolved() && !isResolvable(generics[i])) 172 unsatisfied.add(generics[i]); 173 return (VersionConstraint[]) unsatisfied.toArray(new VersionConstraint[unsatisfied.size()]); 174 } 175 176 179 public boolean isResolvable(ImportPackageSpecification constraint) { 180 ExportPackageDescription[] exports = constraint.getBundle().getContainingState().getExportedPackages(); 181 for (int i = 0; i < exports.length; i++) 182 if (constraint.isSatisfiedBy(exports[i])) 183 return true; 184 return false; 185 } 186 187 private boolean isResolvable(GenericSpecification constraint) { 188 Map genericCapabilities = getGenericsMap(constraint.getBundle().getContainingState(), true); 189 Set genericSet = (Set) genericCapabilities.get(constraint.getName()); 190 if (genericSet == null) 191 return false; 192 for (Iterator iter = genericSet.iterator(); iter.hasNext();) 193 if (constraint.isSatisfiedBy((GenericDescription) iter.next())) 194 return true; 195 return false; 196 } 197 198 201 public boolean isResolvable(BundleSpecification specification) { 202 return isBundleConstraintResolvable(specification); 203 } 204 205 208 public boolean isResolvable(HostSpecification specification) { 209 return isBundleConstraintResolvable(specification); 210 } 211 212 215 private boolean isBundleConstraintResolvable(VersionConstraint constraint) { 216 BundleDescription[] availableBundles = constraint.getBundle().getContainingState().getBundles(constraint.getName()); 217 for (int i = 0; i < availableBundles.length; i++) 218 if (availableBundles[i].isResolved() && constraint.isSatisfiedBy(availableBundles[i])) 219 return true; 220 return false; 221 } 222 223 public Object [][] sortBundles(BundleDescription[] toSort) { 224 List references = new ArrayList(toSort.length); 225 for (int i = 0; i < toSort.length; i++) 226 if (toSort[i].isResolved()) 227 buildReferences(toSort[i], references); 228 return ComputeNodeOrder.computeNodeOrder(toSort, (Object [][]) references.toArray(new Object [references.size()][])); 229 } 230 231 private void buildReferences(BundleDescription description, List references) { 232 HostSpecification host = description.getHost(); 233 if (host != null) { 235 if (host.getHosts() != null) { 237 BundleDescription[] hosts = host.getHosts(); 238 for (int i = 0; i < hosts.length; i++) 239 if (hosts[i] != description) 240 references.add(new Object [] {description, hosts[i]}); 241 } 242 } else { 243 buildReferences(description, ((BundleDescriptionImpl) description).getBundleDependencies(), references); 245 } 246 } 247 248 private void buildReferences(BundleDescription description, List dependencies, List references) { 249 for (Iterator iter = dependencies.iterator(); iter.hasNext();) 250 addReference(description, (BundleDescription) iter.next(), references); 251 } 252 253 private void addReference(BundleDescription description, BundleDescription reference, List references) { 254 if (description == reference || reference == null) 256 return; 257 BundleDescription[] fragments = reference.getFragments(); 258 for (int i = 0; i < fragments.length; i++) { 259 if (fragments[i].isResolved()) { 260 ExportPackageDescription[] exports = fragments[i].getExportPackages(); 261 if (exports.length > 0) 262 references.add(new Object [] {description, fragments[i]}); 263 } 264 } 265 references.add(new Object [] {description, reference}); 266 } 267 268 public ExportPackageDescription[] getVisiblePackages(BundleDescription bundle) { 269 return getVisiblePackages(bundle, 0); 270 } 271 272 public ExportPackageDescription[] getVisiblePackages(BundleDescription bundle, int options) { 273 StateImpl state = (StateImpl) bundle.getContainingState(); 274 boolean strict = false; 275 if (state != null) 276 strict = state.inStrictMode(); 277 ArrayList orderedPkgList = new ArrayList(); Set pkgSet = new HashSet(); 279 Set importList = new HashSet(); ImportPackageSpecification[] imports = bundle.getImportPackages(); 282 for (int i = 0; i < imports.length; i++) { 283 ExportPackageDescription pkgSupplier = (ExportPackageDescription) imports[i].getSupplier(); 284 if (pkgSupplier == null) 285 continue; 286 if (!isSystemExport(pkgSupplier, options) && !pkgSet.contains(pkgSupplier)) { 287 orderedPkgList.add(pkgSupplier); 288 pkgSet.add(pkgSupplier); 289 } 290 BundleSpecification[] requires = pkgSupplier.getExporter().getRequiredBundles(); 292 Set visited = new HashSet(); 293 visited.add(bundle); Set importNames = new HashSet(1); 295 importNames.add(imports[i].getName()); 296 for (int j = 0; j < requires.length; j++) { 297 BundleDescription bundleSupplier = (BundleDescription) requires[j].getSupplier(); 298 if (bundleSupplier != null) 299 getPackages(bundleSupplier, bundle.getSymbolicName(), importList, orderedPkgList, pkgSet, visited, strict, importNames, options); 300 } 301 importList.add(imports[i].getName()); } 303 BundleSpecification[] requires = bundle.getRequiredBundles(); 305 Set visited = new HashSet(requires.length); 306 visited.add(bundle); for (int i = 0; i < requires.length; i++) { 308 BundleDescription bundleSupplier = (BundleDescription) requires[i].getSupplier(); 309 if (bundleSupplier != null) 310 getPackages(bundleSupplier, bundle.getSymbolicName(), importList, orderedPkgList, pkgSet, visited, strict, null, options); 311 } 312 return (ExportPackageDescription[]) orderedPkgList.toArray(new ExportPackageDescription[orderedPkgList.size()]); 313 } 314 315 private void getPackages(BundleDescription requiredBundle, String symbolicName, Set importList, ArrayList orderedPkgList, Set pkgSet, Set visited, boolean strict, Set pkgNames, int options) { 316 if (visited.contains(requiredBundle)) 317 return; visited.add(requiredBundle); 319 ExportPackageDescription[] exports = requiredBundle.getSelectedExports(); 321 HashSet exportNames = new HashSet(exports.length); for (int i = 0; i < exports.length; i++) 323 if ((pkgNames == null || pkgNames.contains(exports[i].getName())) && !isSystemExport(exports[i], options) && isFriend(symbolicName, exports[i], strict) && !importList.contains(exports[i].getName()) && !pkgSet.contains(exports[i])) { 324 if (!exportNames.contains(exports[i].getName())) { 325 orderedPkgList.add(exports[i]); 327 pkgSet.add(exports[i]); 328 exportNames.add(exports[i].getName()); 329 } 330 } 331 BundleSpecification[] requiredBundles = requiredBundle.getRequiredBundles(); 333 for (int i = 0; i < requiredBundles.length; i++) { 334 if (requiredBundles[i].getSupplier() == null) 335 continue; 336 if (requiredBundles[i].isExported()) { 337 getPackages((BundleDescription) requiredBundles[i].getSupplier(), symbolicName, importList, orderedPkgList, pkgSet, visited, strict, pkgNames, options); 339 } else if (exportNames.size() > 0) { 340 Set tmpVisited = new HashSet(); 342 getPackages((BundleDescription) requiredBundles[i].getSupplier(), symbolicName, importList, orderedPkgList, pkgSet, tmpVisited, strict, exportNames, options); 343 } 344 } 345 } 346 347 private boolean isSystemExport(ExportPackageDescription export, int options) { 348 if ((options & VISIBLE_INCLUDE_EE_PACKAGES) != 0) 349 return false; 350 return ((Integer ) export.getDirective(ExportPackageDescriptionImpl.EQUINOX_EE)).intValue() >= 0; 351 } 352 353 private boolean isFriend(String consumerBSN, ExportPackageDescription export, boolean strict) { 354 if (!strict) 355 return true; String [] friends = (String []) export.getDirective(Constants.FRIENDS_DIRECTIVE); 357 if (friends == null) 358 return true; for (int i = 0; i < friends.length; i++) 360 if (friends[i].equals(consumerBSN)) 361 return true; return false; 363 } 364 365 public int getAccessCode(BundleDescription bundle, ExportPackageDescription export) { 366 if (((Boolean ) export.getDirective(Constants.INTERNAL_DIRECTIVE)).booleanValue()) 367 return ACCESS_DISCOURAGED; 368 if (!isFriend(bundle.getSymbolicName(), export, true)) return ACCESS_DISCOURAGED; 370 return ACCESS_ENCOURAGED; 371 } 372 373 public static StateHelper getInstance() { 374 return instance; 375 } 376 } 377 | Popular Tags |