1 11 package org.eclipse.pde.internal.ui.search.dependencies; 12 13 import java.io.FileNotFoundException ; 14 import java.io.FileOutputStream ; 15 import java.io.PrintWriter ; 16 import java.lang.reflect.InvocationTargetException ; 17 import java.util.ArrayList ; 18 import java.util.Collection ; 19 import java.util.HashMap ; 20 import java.util.HashSet ; 21 import java.util.Iterator ; 22 import java.util.LinkedList ; 23 import java.util.List ; 24 import java.util.Map ; 25 import java.util.Set ; 26 import java.util.Stack ; 27 import java.util.StringTokenizer ; 28 29 import org.eclipse.core.resources.IFile; 30 import org.eclipse.core.resources.IProject; 31 import org.eclipse.core.resources.IResource; 32 import org.eclipse.core.resources.ProjectScope; 33 import org.eclipse.core.runtime.CoreException; 34 import org.eclipse.core.runtime.IProgressMonitor; 35 import org.eclipse.core.runtime.SubProgressMonitor; 36 import org.eclipse.jdt.core.IJavaElement; 37 import org.eclipse.jdt.core.IJavaProject; 38 import org.eclipse.jdt.core.IPackageFragmentRoot; 39 import org.eclipse.jdt.core.IParent; 40 import org.eclipse.jdt.core.JavaCore; 41 import org.eclipse.jdt.core.JavaModelException; 42 import org.eclipse.jdt.core.search.IJavaSearchConstants; 43 import org.eclipse.jdt.core.search.IJavaSearchScope; 44 import org.eclipse.jdt.core.search.SearchEngine; 45 import org.eclipse.jdt.core.search.SearchMatch; 46 import org.eclipse.jdt.core.search.SearchParticipant; 47 import org.eclipse.jdt.core.search.SearchPattern; 48 import org.eclipse.jdt.core.search.SearchRequestor; 49 import org.eclipse.osgi.service.resolver.BaseDescription; 50 import org.eclipse.osgi.service.resolver.BundleDescription; 51 import org.eclipse.osgi.service.resolver.BundleSpecification; 52 import org.eclipse.osgi.service.resolver.ExportPackageDescription; 53 import org.eclipse.osgi.service.resolver.ImportPackageSpecification; 54 import org.eclipse.osgi.util.ManifestElement; 55 import org.eclipse.osgi.util.NLS; 56 import org.eclipse.pde.core.build.IBuild; 57 import org.eclipse.pde.core.build.IBuildEntry; 58 import org.eclipse.pde.core.plugin.IPluginBase; 59 import org.eclipse.pde.core.plugin.IPluginImport; 60 import org.eclipse.pde.core.plugin.IPluginModelBase; 61 import org.eclipse.pde.core.plugin.PluginRegistry; 62 import org.eclipse.pde.internal.core.ICoreConstants; 63 import org.eclipse.pde.internal.core.PDECore; 64 import org.eclipse.pde.internal.core.build.WorkspaceBuildModel; 65 import org.eclipse.pde.internal.core.bundle.BundlePluginBase; 66 import org.eclipse.pde.internal.core.converter.PluginConverter; 67 import org.eclipse.pde.internal.core.ibundle.IBundle; 68 import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase; 69 import org.eclipse.pde.internal.core.ibundle.IManifestHeader; 70 import org.eclipse.pde.internal.core.plugin.PluginImport; 71 import org.eclipse.pde.internal.core.search.PluginJavaSearchUtil; 72 import org.eclipse.pde.internal.core.text.bundle.ImportPackageHeader; 73 import org.eclipse.pde.internal.core.text.bundle.ImportPackageObject; 74 import org.eclipse.pde.internal.core.text.bundle.RequireBundleHeader; 75 import org.eclipse.pde.internal.core.text.bundle.RequireBundleObject; 76 import org.eclipse.pde.internal.ui.PDEUIMessages; 77 import org.eclipse.ui.actions.WorkspaceModifyOperation; 78 import org.osgi.framework.BundleException; 79 import org.osgi.framework.Constants; 80 import org.osgi.framework.Version; 81 82 public class AddNewDependenciesOperation extends WorkspaceModifyOperation { 83 84 protected IProject fProject; 85 protected IBundlePluginModelBase fBase; 86 private boolean fNewDependencies = false; 87 88 protected static class ReferenceFinder extends SearchRequestor { 89 private boolean found = false; 90 public void acceptSearchMatch(SearchMatch match) throws CoreException { 91 found = true; 92 } 93 public boolean foundMatches() { 94 return found; 95 } 96 } 97 98 public AddNewDependenciesOperation(IProject project, IBundlePluginModelBase base) { 99 fProject = project; 100 fBase = base; 101 } 102 103 protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException , InterruptedException { 104 monitor.beginTask(PDEUIMessages.AddNewDependenciesOperation_mainTask, 100); 105 final IBundle bundle = fBase.getBundleModel().getBundle(); 106 final Set ignorePkgs = new HashSet (); 107 final String [] secDeps = findSecondaryBundles(bundle, ignorePkgs); 108 if (secDeps == null || secDeps.length == 0) { 109 monitor.done(); 110 return; 111 } 112 monitor.worked(4); 113 findImportPackages(bundle, ignorePkgs); 114 monitor.worked(2); 115 addProjectPackages(bundle, ignorePkgs); 116 monitor.worked(4); 117 118 final Map additionalDeps = new HashMap (); 119 monitor.subTask(PDEUIMessages.AddNewDependenciesOperation_searchProject); 120 121 boolean useRequireBundle = new ProjectScope(fProject).getNode(PDECore.PLUGIN_ID).getBoolean(ICoreConstants.RESOLVE_WITH_REQUIRE_BUNDLE, true); 122 findSecondaryDependencies(secDeps, ignorePkgs, additionalDeps, bundle, useRequireBundle, new SubProgressMonitor(monitor, 80)); 123 handleNewDependencies(additionalDeps, 124 useRequireBundle, new SubProgressMonitor(monitor, 10)); 125 monitor.done(); 126 } 127 128 public boolean foundNewDependencies() { 129 return fNewDependencies; 130 } 131 132 protected String [] findSecondaryBundles(IBundle bundle, Set ignorePkgs) { 133 String [] secDeps = getSecondaryDependencies(); 134 if (secDeps == null) 135 return null; 136 Set manifestPlugins = findManifestPlugins(bundle, ignorePkgs); 137 138 List result = new LinkedList (); 139 for (int i = 0; i < secDeps.length; i++) 140 if (!manifestPlugins.contains(secDeps[i])) 141 result.add(secDeps[i]); 142 143 return (String [])result.toArray(new String [result.size()]); 144 } 145 146 private String [] getSecondaryDependencies() { 147 IBuild build = getBuild(); 148 if (build != null) { 149 IBuildEntry be = build.getEntry(IBuildEntry.SECONDARY_DEPENDENCIES); 150 if (be != null) 151 return be.getTokens(); 152 } 153 return null; 154 } 155 156 protected final IBuild getBuild() { 157 IFile buildProps = fProject.getFile("build.properties"); if (buildProps != null) { 159 WorkspaceBuildModel model = new WorkspaceBuildModel(buildProps); 160 if (model != null) 161 return model.getBuild(); 162 } 163 return null; 164 } 165 166 private Set findManifestPlugins(IBundle bundle, Set ignorePkgs) { 167 IManifestHeader header = bundle.getManifestHeader(Constants.REQUIRE_BUNDLE); 168 if (header == null) 169 return new HashSet (0); 170 Set plugins = (header instanceof RequireBundleHeader) ? findManifestPlugins((RequireBundleHeader)header, ignorePkgs): 171 findManifestPlugins(ignorePkgs); 172 if (plugins.contains("org.eclipse.core.runtime")) plugins.add("system.bundle"); return plugins; 175 } 176 177 private Set findManifestPlugins(RequireBundleHeader header, Set ignorePkgs) { 178 RequireBundleObject[] bundles = header.getRequiredBundles(); 179 Set result = new HashSet ((4/3) * (bundles.length) + 2); 180 ArrayList plugins = new ArrayList (); 181 for (int i = 0; i < bundles.length; i++) { 182 String id = bundles[i].getId(); 183 result.add(id); 184 IPluginModelBase base = PluginRegistry.findModel(id); 185 if (base != null) { 186 ExportPackageDescription[] exportedPkgs = findExportedPackages(base.getBundleDescription()); 187 for (int j = 0; j < exportedPkgs.length; j++) 188 ignorePkgs.add(exportedPkgs[j].getName()); 189 plugins.add(base.getPluginBase()); 190 } 191 } 192 return result; 193 } 194 195 private Set findManifestPlugins(Set ignorePkgs) { 196 BundleSpecification[] bundles = fBase.getBundleDescription().getRequiredBundles(); 197 Set result = new HashSet ((4/3) * (bundles.length) + 2); 198 ArrayList plugins = new ArrayList (); 199 for (int i = 0; i < bundles.length; i++) { 200 String id = bundles[i].getName(); 201 result.add(id); 202 IPluginModelBase base = PluginRegistry.findModel(id); 203 if (base != null) { 204 ExportPackageDescription[] exportedPkgs = findExportedPackages(base.getBundleDescription()); 205 for (int j = 0; j < exportedPkgs.length; j++) 206 ignorePkgs.add(exportedPkgs[j].getName()); 207 plugins.add(base.getPluginBase()); 208 } 209 } 210 return result; 211 } 212 213 protected final ExportPackageDescription[] findExportedPackages(BundleDescription desc) { 214 if (desc != null) { 215 IBundle bundle = fBase.getBundleModel().getBundle(); 216 String value = bundle.getHeader(Constants.BUNDLE_SYMBOLICNAME); 217 int index = (value != null) ? value.indexOf(';') : -1; 218 String projectBundleId = (index > 0) ? value.substring(0, index) : value; 219 List result = new LinkedList (); 220 Stack stack = new Stack (); 221 stack.add(desc); 222 while (!stack.isEmpty()) { 223 BundleDescription bdesc = (BundleDescription) stack.pop(); 224 ExportPackageDescription[] expkgs = bdesc.getExportPackages(); 225 for (int i = 0; i < expkgs.length; i++) 226 if (addPackage(projectBundleId, expkgs[i])) 227 result.add(expkgs[i]); 228 229 BundleSpecification[] requiredBundles = bdesc.getRequiredBundles(); 231 for (int i = 0; i < requiredBundles.length; i++) 232 if (requiredBundles[i].isExported()) { 233 BaseDescription bd = requiredBundles[i].getSupplier(); 234 if (bd != null && bd instanceof BundleDescription) 235 stack.add(bd); 236 } 237 } 238 return (ExportPackageDescription[]) result.toArray(new ExportPackageDescription[result.size()]); 239 } 240 return new ExportPackageDescription[0]; 241 } 242 243 private boolean addPackage(String symbolicName, ExportPackageDescription pkg) { 244 if (symbolicName == null) 245 return true; 246 String [] friends = (String [])pkg.getDirective(ICoreConstants.FRIENDS_DIRECTIVE); 247 if (friends != null) { 248 for (int i = 0; i < friends.length; i++) { 249 if (symbolicName.equals(friends[i])) 250 return true; 251 } 252 return false; 253 } 254 return !(((Boolean )pkg.getDirective(ICoreConstants.INTERNAL_DIRECTIVE)).booleanValue()); 255 } 256 257 protected final void findImportPackages(IBundle bundle, Set ignorePkgs) { 258 IManifestHeader header = bundle.getManifestHeader(Constants.IMPORT_PACKAGE); 259 if (header == null || header.getValue() == null) 260 return; 261 if (header instanceof ImportPackageHeader) { 262 ImportPackageObject[] pkgs = ((ImportPackageHeader)header).getPackages(); 263 for (int i = 0; i < pkgs.length; i++) 264 ignorePkgs.add(pkgs[i].getName()); 265 } else { 266 ImportPackageSpecification[] pkgs = fBase.getBundleDescription().getImportPackages(); 267 for (int i = 0; i < pkgs.length; i++) 268 ignorePkgs.add(pkgs[i].getName()); 269 } 270 } 271 272 protected void findSecondaryDependencies(String [] secDeps, Set ignorePkgs, Map newDeps, IBundle bundle, boolean useRequireBundle, 273 IProgressMonitor monitor) { 274 IJavaProject jProject = JavaCore.create(fProject); 275 SearchEngine engine = new SearchEngine(); 276 if (ignorePkgs == null) 277 ignorePkgs = new HashSet (2); 278 monitor.beginTask(PDEUIMessages.AddNewDependenciesOperation_searchProject, secDeps.length); 279 for (int j = 0; j < secDeps.length; j++) { 280 try { 281 if (monitor.isCanceled()) 282 return; 283 IProgressMonitor subMonitor = new SubProgressMonitor(monitor, 1); 284 String pluginId = secDeps[j]; 285 IPluginModelBase base = PluginRegistry.findModel(secDeps[j]); 286 if (base != null) { 287 ExportPackageDescription[] exported = findExportedPackages(base.getBundleDescription()); 288 IJavaSearchScope searchScope = PluginJavaSearchUtil.createSeachScope(jProject); 289 subMonitor.beginTask(NLS.bind(PDEUIMessages.AddNewDependenciesOperation_searchForDependency, pluginId), exported.length); 290 for (int i = 0; i < exported.length; i++) { 291 String pkgName = exported[i].getName(); 292 if (!ignorePkgs.contains(pkgName)) { 293 ReferenceFinder requestor = new ReferenceFinder(); 294 engine.search( 295 SearchPattern.createPattern(pkgName, IJavaSearchConstants.PACKAGE, IJavaSearchConstants.REFERENCES, SearchPattern.R_EXACT_MATCH), 296 new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, 297 searchScope, 298 requestor, 299 null); 300 if (requestor.foundMatches()) { 301 fNewDependencies = true; 302 ignorePkgs.add(pkgName); 303 newDeps.put(exported[i], pluginId); 304 if (useRequireBundle) { 305 for (; i < exported.length; i++) 307 ignorePkgs.add(exported[i].getName()); 308 } 309 } 310 } 311 subMonitor.worked(1); 312 } 313 } 314 subMonitor.done(); 315 } catch (CoreException e) { 316 monitor.done(); 317 } 318 } 319 } 320 321 protected void addProjectPackages(IBundle bundle, Set ignorePkgs) { 322 IBuild build = getBuild(); 323 if (build == null) 324 return; 325 IBuildEntry binIncludes = build.getEntry(IBuildEntry.BIN_INCLUDES); 326 if (binIncludes != null) { 327 String value = bundle.getHeader(Constants.BUNDLE_CLASSPATH); 328 if (value == null) 329 value = "."; ManifestElement elems[]; 331 try { 332 elems = ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, value); 333 } catch (BundleException e) { 334 return; 335 } 336 IJavaProject jProject = JavaCore.create(fProject); 337 for (int i = 0; i < elems.length; i++) { 338 String library = elems[i].getValue(); 339 if (binIncludes.contains(library)) { 341 IBuildEntry entry = build.getEntry(IBuildEntry.JAR_PREFIX + library); 343 if (entry != null) { 344 String [] resources = entry.getTokens(); 345 for (int j = 0; j < resources.length; j++) 346 addPackagesFromResource(jProject, fProject.findMember(resources[j]), ignorePkgs); 347 } else { 348 addPackagesFromResource(jProject, fProject.findMember(library), ignorePkgs); 350 } 351 } else { 352 StringTokenizer tokenizer = new StringTokenizer (library,"/"); StringBuffer buffer = new StringBuffer (); 355 while (tokenizer.hasMoreTokens()) { 356 buffer.append(tokenizer.nextToken()).append('/'); 357 if (binIncludes.contains(buffer.toString())) 358 addPackagesFromResource(jProject, fProject.findMember(library), ignorePkgs); 359 } 360 } 361 } 362 } 363 } 364 365 private void addPackagesFromResource(IJavaProject jProject, IResource res, Set ignorePkgs) { 366 if (res == null) 367 return; 368 try { 369 IPackageFragmentRoot root = jProject.getPackageFragmentRoot(res); 370 IJavaElement[] children = root.getChildren(); 371 for (int i = 0; i < children.length; i++) { 372 String pkgName = children[i].getElementName(); 373 if (children[i] instanceof IParent) 374 if (pkgName.length() > 0 && ((IParent)children[i]).hasChildren()) 375 ignorePkgs.add(children[i].getElementName()); 376 } 377 } catch (JavaModelException e) { 378 } 379 } 380 381 protected void handleNewDependencies(final Map additionalDeps, final boolean useRequireBundle, IProgressMonitor monitor) { 382 if (!additionalDeps.isEmpty()) 383 addDependencies(additionalDeps, useRequireBundle); 384 monitor.done(); 385 } 386 387 protected void addDependencies(final Map depsToAdd, boolean useRequireBundle) { 388 if (useRequireBundle) { 389 Collection plugins = depsToAdd.values(); 390 minimizeBundles(plugins); 391 IBuild build = getBuild(); 392 IPluginBase pbase = fBase.getPluginBase(); 393 if (pbase == null ) { 394 addRequireBundles(plugins, fBase.getBundleModel().getBundle(), build.getEntry(IBuildEntry.SECONDARY_DEPENDENCIES)); 395 } 396 else 397 addRequireBundles(plugins, pbase, build.getEntry(IBuildEntry.SECONDARY_DEPENDENCIES)); 398 try { 399 build.write("", new PrintWriter (new FileOutputStream (fProject.getFile("build.properties").getFullPath().toFile()))); } catch (FileNotFoundException e) { 401 } 402 } else { 403 Collection pkgs = depsToAdd.keySet(); 404 addImportPackages(pkgs, fBase.getBundleModel().getBundle()); 405 } 406 } 407 408 protected final void addImportPackages(final Collection depsToAdd, final IBundle bundle) { 409 Iterator it = depsToAdd.iterator(); 410 IManifestHeader mheader = bundle.getManifestHeader(Constants.IMPORT_PACKAGE); 411 if (mheader == null) { 413 bundle.setHeader(Constants.IMPORT_PACKAGE, new String ()); 414 mheader = bundle.getManifestHeader(Constants.IMPORT_PACKAGE); 415 } 416 if (mheader instanceof ImportPackageHeader) { 417 ImportPackageHeader header = (ImportPackageHeader) mheader; 418 String versionAttr = (BundlePluginBase.getBundleManifestVersion(bundle) < 2) ? 419 ICoreConstants.PACKAGE_SPECIFICATION_VERSION : Constants.VERSION_ATTRIBUTE; 420 while (it.hasNext()) { 421 ImportPackageObject obj = new ImportPackageObject(header, (ExportPackageDescription)it.next(), versionAttr); 422 header.addPackage(obj); 423 } 424 } else { 425 String currentValue = (mheader != null) ? mheader.getValue() : null; 426 StringBuffer buffer = (currentValue == null) ? new StringBuffer () : new StringBuffer (currentValue).append(", "); while(it.hasNext()) { 428 ExportPackageDescription desc = (ExportPackageDescription)it.next(); 429 String value = (desc.getVersion().equals(Version.emptyVersion)) ? desc.getName() : 430 desc.getName() + "; version=\"" + desc.getVersion() + "\""; buffer.append(value).append(PluginConverter.LIST_SEPARATOR); 433 } 434 if (buffer.length() > 0) 435 buffer.setLength(buffer.length() - PluginConverter.LIST_SEPARATOR.length()); 436 bundle.setHeader(Constants.IMPORT_PACKAGE, buffer.toString()); 437 } 438 } 439 440 protected final void addRequireBundles(final Collection depsToAdd, final IBundle bundle, IBuildEntry entry) { 441 if (bundle == null) 442 return; 443 HashSet added = new HashSet (); 444 Iterator it = depsToAdd.iterator(); 445 IManifestHeader mheader = bundle.getManifestHeader(Constants.REQUIRE_BUNDLE); 446 if (mheader instanceof RequireBundleHeader) { 447 RequireBundleHeader header = (RequireBundleHeader) mheader; 448 while (it.hasNext()) { 449 String pluginId = (String )it.next(); 450 if (!added.contains(pluginId)) 451 try { 452 header.addBundle(pluginId); 453 added.add(pluginId); 454 entry.removeToken(pluginId); 455 } catch (CoreException e) { 456 } 457 } 458 } 459 else { 460 String currentValue = (mheader != null) ? mheader.getValue() : null; 461 StringBuffer buffer = (currentValue == null) ? new StringBuffer () : new StringBuffer (currentValue).append(", "); while(it.hasNext()) { 463 String pluginId = (String ) it.next(); 464 if (!added.contains(pluginId)) 465 try { 466 buffer.append(pluginId).append(PluginConverter.LIST_SEPARATOR); 467 added.add(pluginId); 468 entry.removeToken(pluginId); 469 } catch (CoreException e) { 470 } 471 } 472 if (buffer.length() > 0) 473 buffer.setLength(buffer.length() - PluginConverter.LIST_SEPARATOR.length()); 474 bundle.setHeader(Constants.REQUIRE_BUNDLE, buffer.toString()); 475 } 476 } 477 478 protected final void addRequireBundles(final Collection depsToAdd, final IPluginBase base, IBuildEntry entry) { 479 HashSet added = new HashSet (); 480 Iterator it = depsToAdd.iterator(); 481 base.getImports(); 483 while (it.hasNext()) { 484 String pluginId = (String )it.next(); 485 if (!added.contains(pluginId)) 486 try { 487 PluginImport plugin = new PluginImport(); 488 ManifestElement element = ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, pluginId)[0]; 489 plugin.load(element, 1); 490 plugin.setModel(base.getModel()); 491 base.add(plugin); 492 added.add(pluginId); 493 if (entry != null && entry.contains(pluginId)) 494 entry.removeToken(pluginId); 495 } catch (BundleException e){ 496 } catch (CoreException e) { 497 } 498 } 499 } 500 501 protected final void minimizeBundles(Collection pluginIds) { 502 Stack stack = new Stack (); 503 Iterator it = pluginIds.iterator(); 504 while (it.hasNext()) 505 stack.push(it.next().toString()); 506 507 while (!stack.isEmpty()) { 508 IPluginModelBase base = PluginRegistry.findModel(stack.pop().toString()); 509 if (base == null) 510 continue; 511 IPluginImport[] imports = base.getPluginBase().getImports(); 512 513 for (int j = 0; j < imports.length; j++) 514 if (imports[j].isReexported()) { 515 String reExportedId = imports[j].getId(); 516 pluginIds.remove(imports[j].getId()); 517 stack.push(reExportedId); 518 } 519 } 520 } 521 } 522 | Popular Tags |