1 11 package org.eclipse.pde.internal.core; 12 13 import java.io.File ; 14 import java.util.ArrayList ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.Map ; 19 import java.util.Stack ; 20 import java.util.TreeMap ; 21 22 import org.eclipse.core.resources.IFile; 23 import org.eclipse.core.resources.IProject; 24 import org.eclipse.core.resources.IResource; 25 import org.eclipse.core.runtime.CoreException; 26 import org.eclipse.core.runtime.IPath; 27 import org.eclipse.core.runtime.Path; 28 import org.eclipse.core.runtime.Platform; 29 import org.eclipse.jdt.core.IClasspathContainer; 30 import org.eclipse.jdt.core.IClasspathEntry; 31 import org.eclipse.jdt.core.JavaCore; 32 import org.eclipse.osgi.service.resolver.BaseDescription; 33 import org.eclipse.osgi.service.resolver.BundleDescription; 34 import org.eclipse.osgi.service.resolver.BundleSpecification; 35 import org.eclipse.osgi.service.resolver.ExportPackageDescription; 36 import org.eclipse.osgi.service.resolver.HostSpecification; 37 import org.eclipse.osgi.service.resolver.ImportPackageSpecification; 38 import org.eclipse.osgi.service.resolver.StateHelper; 39 import org.eclipse.pde.core.build.IBuild; 40 import org.eclipse.pde.core.build.IBuildEntry; 41 import org.eclipse.pde.core.plugin.IPluginModelBase; 42 import org.eclipse.pde.core.plugin.PluginRegistry; 43 import org.eclipse.pde.internal.build.IBuildPropertiesConstants; 44 import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase; 45 46 public class RequiredPluginsClasspathContainer extends PDEClasspathContainer implements IClasspathContainer { 47 48 private IPluginModelBase fModel; 49 private IBuild fBuild; 50 51 private static boolean DEBUG = false; 52 53 private IClasspathEntry[] fEntries = null; 54 55 static { 56 DEBUG = PDECore.getDefault().isDebugging() 57 && "true".equals(Platform.getDebugOption("org.eclipse.pde.core/classpath")); } 59 60 63 public RequiredPluginsClasspathContainer(IPluginModelBase model) { 64 this(model, null); 65 } 66 67 public RequiredPluginsClasspathContainer(IPluginModelBase model, IBuild build) { 68 fModel = model; 69 fBuild = build; 70 } 71 72 76 public int getKind() { 77 return K_APPLICATION; 78 } 79 80 84 public IPath getPath() { 85 return PDECore.REQUIRED_PLUGINS_CONTAINER_PATH; 86 } 87 88 92 public String getDescription() { 93 return PDECoreMessages.RequiredPluginsClasspathContainer_description; 94 } 95 96 100 public IClasspathEntry[] getClasspathEntries() { 101 if (fModel == null) { 102 if (DEBUG) { 103 System.out.println("********Returned an empty container"); System.out.println(); 105 } 106 return new IClasspathEntry[0]; 107 } 108 if (fEntries == null) { 109 fEntries = computePluginEntries(); 110 } 111 if (DEBUG) { 112 System.out.println("Dependencies for plugin '" + fModel.getPluginBase().getId() + "':"); for (int i = 0; i < fEntries.length; i++) { 114 System.out.println(fEntries[i]); 115 } 116 System.out.println(); 117 } 118 return fEntries; 119 } 120 121 private IClasspathEntry[] computePluginEntries() { 122 ArrayList entries = new ArrayList (); 123 try { 124 BundleDescription desc = fModel.getBundleDescription(); 125 if (desc == null) 126 return new IClasspathEntry[0]; 127 128 Map map = retrieveVisiblePackagesFromState(desc); 129 130 HashSet added = new HashSet (); 131 132 added.add(desc); 134 135 HostSpecification host = desc.getHost(); 136 if (host != null) { 137 addHostPlugin(host, added, map, entries); 138 } else if ("true".equals(System.getProperty("pde.allowCycles"))) { BundleDescription[] fragments = desc.getFragments(); 140 for (int i = 0; i < fragments.length; i++) { 141 if (fragments[i].isResolved()) { 142 addPlugin(fragments[i], false, map, entries); 143 } 144 } 145 } 146 147 BundleSpecification[] required = desc.getRequiredBundles(); 149 for (int i = 0; i < required.length; i++) { 150 addDependency((BundleDescription)required[i].getSupplier(), added, map, entries); 151 } 152 153 if (fBuild == null) 154 fBuild = ClasspathUtilCore.getBuild(fModel); 155 if (fBuild != null) 156 addSecondaryDependencies(desc, added, entries); 157 158 Map sortedMap = new TreeMap (); 161 Iterator iter = map.keySet().iterator(); 162 while (iter.hasNext()) { 163 BundleDescription bundle = (BundleDescription)iter.next(); 164 sortedMap.put(bundle.toString(), bundle); 165 } 166 167 iter = sortedMap.values().iterator(); 168 while (iter.hasNext()) { 169 BundleDescription bundle = (BundleDescription)iter.next(); 170 IPluginModelBase model = PluginRegistry.findModel(bundle); 171 if (model != null && model.isEnabled()) 172 addDependencyViaImportPackage(model.getBundleDescription(), added, map, entries); 173 } 174 175 if (fBuild != null) 176 addExtraClasspathEntries(added, entries); 177 178 } catch (CoreException e) { 179 } 180 return (IClasspathEntry[])entries.toArray(new IClasspathEntry[entries.size()]); 181 } 182 183 private Map retrieveVisiblePackagesFromState(BundleDescription desc) { 184 Map visiblePackages = new HashMap (); 185 StateHelper helper = Platform.getPlatformAdmin().getStateHelper(); 186 addVisiblePackagesFromState(helper, desc, visiblePackages); 187 if (desc.getHost() != null) 188 addVisiblePackagesFromState(helper, (BundleDescription)desc.getHost().getSupplier(), visiblePackages); 189 return visiblePackages; 190 } 191 192 private void addVisiblePackagesFromState(StateHelper helper, BundleDescription desc, Map visiblePackages) { 193 if (desc == null) 194 return; 195 ExportPackageDescription[] exports = helper.getVisiblePackages(desc); 196 for (int i = 0; i < exports.length; i++) { 197 BundleDescription exporter = exports[i].getExporter(); 198 if (exporter == null) 199 continue; 200 ArrayList list = (ArrayList )visiblePackages.get(exporter); 201 if (list == null) 202 list = new ArrayList (); 203 Rule rule = getRule(helper, desc, exports[i]); 204 if (!list.contains(rule)) 205 list.add(rule); 206 visiblePackages.put(exporter, list); 207 } 208 } 209 210 private Rule getRule(StateHelper helper, BundleDescription desc, ExportPackageDescription export) { 211 Rule rule = new Rule(); 212 rule.discouraged = helper.getAccessCode(desc, export) == StateHelper.ACCESS_DISCOURAGED; 213 String name = export.getName(); 214 rule.path = (name.equals(".")) ? new Path("*") : new Path(name.replaceAll("\\.", "/") + "/*"); return rule; 216 } 217 218 protected void addDependencyViaImportPackage(BundleDescription desc, HashSet added, Map map, ArrayList entries) throws CoreException { 219 if (desc == null || !added.add(desc)) 220 return; 221 222 addPlugin(desc, true, map, entries); 223 224 if (hasExtensibleAPI(desc) && desc.getContainingState() != null) { 225 BundleDescription[] fragments = desc.getFragments(); 226 for (int i = 0; i < fragments.length; i++) { 227 if (fragments[i].isResolved()) 228 addDependencyViaImportPackage(fragments[i], added, map, entries); 229 } 230 } 231 } 232 233 private void addDependency(BundleDescription desc, HashSet added, Map map, ArrayList entries) throws CoreException { 234 addDependency(desc, added, map, entries, true); 235 } 236 237 private void addDependency(BundleDescription desc, HashSet added, Map map, ArrayList entries, boolean useInclusion) throws CoreException { 238 if (desc == null || !added.add(desc)) 239 return; 240 241 BundleDescription[] fragments = hasExtensibleAPI(desc) ? desc.getFragments() : new BundleDescription[0]; 242 243 for (int i = 0; i < fragments.length; i++) { 245 if (fragments[i].isResolved() && ClasspathUtilCore.isPatchFragment(fragments[i])) { 246 addDependency(fragments[i], added, map, entries, useInclusion); 247 } 248 } 249 250 addPlugin(desc, useInclusion, map, entries); 251 252 for (int i = 0; i < fragments.length; i++) { 254 if (fragments[i].isResolved() && !ClasspathUtilCore.isPatchFragment(fragments[i])) { 255 addDependency(fragments[i], added, map, entries, useInclusion); 256 } 257 } 258 259 BundleSpecification[] required = desc.getRequiredBundles(); 260 for (int i = 0; i < required.length; i++) { 261 if (required[i].isExported()) { 262 addDependency((BundleDescription)required[i].getSupplier(), added, map, entries, useInclusion); 263 } 264 } 265 } 266 267 private boolean addPlugin(BundleDescription desc, boolean useInclusions, Map map, ArrayList entries) 268 throws CoreException { 269 IPluginModelBase model = PluginRegistry.findModel(desc); 270 if (model == null || !model.isEnabled()) 271 return false; 272 IResource resource = model.getUnderlyingResource(); 273 Rule[] rules = useInclusions ? getInclusions(map, model) : null; 274 if (resource != null) { 275 addProjectEntry(resource.getProject(), rules, entries); 276 } else { 277 addExternalPlugin(model, rules, entries); 278 } 279 return true; 280 } 281 282 private Rule[] getInclusions(Map map, IPluginModelBase model) { 283 BundleDescription desc = model.getBundleDescription(); 284 if (desc == null 285 || "false".equals(System.getProperty("pde.restriction")) || !(fModel instanceof IBundlePluginModelBase) 287 || TargetPlatformHelper.getTargetVersion() < 3.1) 288 return null; 289 290 Rule[] rules; 291 292 if (desc.getHost() != null) 293 rules = getInclusions(map, (BundleDescription)desc.getHost().getSupplier()); 294 else 295 rules = getInclusions(map, desc); 296 297 return (rules.length == 0 && !ClasspathUtilCore.hasBundleStructure(model)) ? null : rules; 298 } 299 300 private Rule[] getInclusions(Map map, BundleDescription desc) { 301 ArrayList list = (ArrayList )map.get(desc); 302 return list != null ? (Rule[])list.toArray(new Rule[list.size()]) : new Rule[0]; 303 } 304 305 private void addHostPlugin(HostSpecification hostSpec, HashSet added, Map map, ArrayList entries) throws CoreException { 306 BaseDescription desc = hostSpec.getSupplier(); 307 308 if (desc instanceof BundleDescription) { 309 BundleDescription host = (BundleDescription)desc; 310 311 if (added.add(host) && addPlugin(host, false, map, entries)) { 313 BundleSpecification[] required = host.getRequiredBundles(); 314 for (int i = 0; i < required.length; i++) { 315 addDependency((BundleDescription)required[i].getSupplier(), added, map, entries); 316 } 317 318 ImportPackageSpecification[] imports = host.getImportPackages(); 320 for (int i = 0; i < imports.length; i++) { 321 BaseDescription supplier = imports[i].getSupplier(); 322 if (supplier instanceof ExportPackageDescription) { 323 addDependencyViaImportPackage(((ExportPackageDescription)supplier).getExporter(), added, map, entries); 324 } 325 } 326 } 327 } 328 } 329 330 private boolean hasExtensibleAPI(BundleDescription desc) { 331 IPluginModelBase model = PluginRegistry.findModel(desc); 332 return model != null ? ClasspathUtilCore.hasExtensibleAPI(model) : false; 333 } 334 335 protected void addExtraClasspathEntries(HashSet added, ArrayList entries) throws CoreException { 336 IBuildEntry[] buildEntries = fBuild.getBuildEntries(); 337 for (int i = 0; i < buildEntries.length; i++) { 338 String name = buildEntries[i].getName(); 339 if (name.equals(IBuildPropertiesConstants.PROPERTY_JAR_EXTRA_CLASSPATH) 340 || name.startsWith(IBuildPropertiesConstants.PROPERTY_EXTRAPATH_PREFIX)) { 341 addExtraClasspathEntries(added, entries, buildEntries[i].getTokens()); 342 } 343 } 344 } 345 346 protected void addExtraClasspathEntries(HashSet added, ArrayList entries, String [] tokens) throws CoreException { 347 for (int i = 0; i < tokens.length; i++) { 348 IPath path = Path.fromPortableString(tokens[i]); 349 if (!path.isAbsolute()) { 350 File file = new File (fModel.getInstallLocation(), path.toString()); 351 if (file.exists()) { 352 IFile resource = PDECore.getWorkspace().getRoot().getFileForLocation(new Path(file.getAbsolutePath())); 353 if (resource != null && resource.getProject().equals(fModel.getUnderlyingResource().getProject())) { 354 addExtraLibrary(resource.getFullPath(), null, entries); 355 continue; 356 } 357 } 358 if (path.segmentCount() >= 3 && "..".equals(path.segment(0))) { path = path.removeFirstSegments(1); 360 path = Path.fromPortableString("platform:/plugin/").append(path); } else { 362 continue; 363 } 364 } 365 366 if (!path.toPortableString().startsWith("platform:")) { addExtraLibrary(path, null, entries); 368 } else { 369 int count = path.getDevice() == null ? 4 : 3; 370 if (path.segmentCount() >= count) { 371 String pluginID = path.segment(count-2); 372 if (added.contains(pluginID)) 373 continue; 374 IPluginModelBase model = PluginRegistry.findModel(pluginID); 375 if (model != null && model.isEnabled()) { 376 path = path.setDevice(null); 377 path = path.removeFirstSegments(count-1); 378 if (model.getUnderlyingResource() == null) { 379 File file = new File (model.getInstallLocation(), path.toOSString()); 380 if (file.exists()) { 381 addExtraLibrary(new Path(file.getAbsolutePath()), model, entries); 382 } 383 } else { 384 IProject project = model.getUnderlyingResource().getProject(); 385 IFile file = project.getFile(path); 386 if (file.exists()) { 387 addExtraLibrary(file.getFullPath(), model, entries); 388 } 389 } 390 } 391 } 392 } 393 } 394 } 395 396 private void addSecondaryDependencies(BundleDescription desc, HashSet added, ArrayList entries) { 397 try { 398 IBuildEntry entry = fBuild.getEntry(IBuildEntry.SECONDARY_DEPENDENCIES); 399 if (entry != null) { 400 String [] tokens = entry.getTokens(); 401 for (int i = 0; i < tokens.length; i++) { 402 String pluginId = tokens[i]; 403 if (added.contains(pluginId)) 404 continue; 405 IPluginModelBase model = PluginRegistry.findModel(pluginId); 407 if (model != null) { 408 Map rules = new HashMap (); 409 findExportedPackages(model.getBundleDescription(), desc, rules); 410 if (model != null) { 411 addDependency(model.getBundleDescription(), added, rules, entries, true); 412 } 413 } 414 } 415 } 416 } catch (CoreException e) { 417 return; 418 } 419 } 420 421 protected final void findExportedPackages(BundleDescription desc, BundleDescription projectDesc, Map map) { 422 if (desc != null) { 423 Stack stack = new Stack (); 424 stack.add(desc); 425 while (!stack.isEmpty()) { 426 BundleDescription bdesc = (BundleDescription) stack.pop(); 427 ExportPackageDescription[] expkgs = bdesc.getExportPackages(); 428 ArrayList rules = new ArrayList (); 429 for (int i = 0; i < expkgs.length; i++) { 430 Rule rule = new Rule(); 431 rule.discouraged = restrictPackage(projectDesc, expkgs[i]); 432 rule.path = new Path(expkgs[i].getName().replaceAll("\\.", "/") + "/*"); rules.add(rule); 434 } 435 map.put(bdesc, rules); 436 437 BundleSpecification[] requiredBundles = bdesc.getRequiredBundles(); 439 for (int i = 0; i < requiredBundles.length; i++) 440 if (requiredBundles[i].isExported()) { 441 BaseDescription bd = requiredBundles[i].getSupplier(); 442 if (bd != null && bd instanceof BundleDescription) 443 stack.add(bd); 444 } 445 } 446 } 447 } 448 449 private boolean restrictPackage(BundleDescription desc, ExportPackageDescription pkg ) { 450 String [] friends = (String [])pkg.getDirective(ICoreConstants.FRIENDS_DIRECTIVE); 451 if (friends != null) { 452 String symbolicName = desc.getSymbolicName(); 453 for (int i = 0; i < friends.length; i++) { 454 if (symbolicName.equals(friends[i])) 455 return false; 456 457 } 458 return true; 459 } 460 return (((Boolean )pkg.getDirective(ICoreConstants.INTERNAL_DIRECTIVE)).booleanValue()); 461 } 462 463 private void addExtraLibrary(IPath path, IPluginModelBase model, ArrayList entries) throws CoreException { 464 IPath srcPath = null; 465 if (model != null) { 466 IPath shortPath = path.removeFirstSegments(path.matchingFirstSegments(new Path(model.getInstallLocation()))); 467 srcPath = ClasspathUtilCore.getSourceAnnotation(model, shortPath.toString()); 468 } else { 469 String filename = ClasspathUtilCore.getSourceZipName(path.lastSegment()); 470 IPath candidate = path.removeLastSegments(1).append(filename); 471 if (PDECore.getWorkspace().getRoot().getFile(candidate).exists()) 472 srcPath = candidate; 473 } 474 IClasspathEntry clsEntry = JavaCore.newLibraryEntry( 475 path, 476 srcPath, 477 null); 478 if (!entries.contains(clsEntry)) 479 entries.add(clsEntry); 480 } 481 } 482 | Popular Tags |