1 11 package org.eclipse.pde.internal.core.builders; 12 13 import java.util.ArrayList ; 14 import java.util.Enumeration ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.List ; 18 import java.util.Set ; 19 import java.util.StringTokenizer ; 20 21 import org.eclipse.core.resources.IContainer; 22 import org.eclipse.core.resources.IFile; 23 import org.eclipse.core.resources.IMarker; 24 import org.eclipse.core.resources.IProject; 25 import org.eclipse.core.resources.IResource; 26 import org.eclipse.core.runtime.CoreException; 27 import org.eclipse.core.runtime.IPath; 28 import org.eclipse.core.runtime.IProgressMonitor; 29 import org.eclipse.core.runtime.IStatus; 30 import org.eclipse.jdt.core.IClasspathEntry; 31 import org.eclipse.jdt.core.IJavaElement; 32 import org.eclipse.jdt.core.IJavaProject; 33 import org.eclipse.jdt.core.IPackageFragment; 34 import org.eclipse.jdt.core.IPackageFragmentRoot; 35 import org.eclipse.jdt.core.JavaCore; 36 import org.eclipse.jdt.core.JavaModelException; 37 import org.eclipse.jdt.launching.JavaRuntime; 38 import org.eclipse.jdt.launching.environments.IExecutionEnvironment; 39 import org.eclipse.osgi.service.resolver.BundleDescription; 40 import org.eclipse.osgi.service.resolver.BundleSpecification; 41 import org.eclipse.osgi.service.resolver.ExportPackageDescription; 42 import org.eclipse.osgi.service.resolver.HostSpecification; 43 import org.eclipse.osgi.service.resolver.ImportPackageSpecification; 44 import org.eclipse.osgi.service.resolver.ResolverError; 45 import org.eclipse.osgi.service.resolver.State; 46 import org.eclipse.osgi.service.resolver.VersionConstraint; 47 import org.eclipse.osgi.service.resolver.VersionRange; 48 import org.eclipse.osgi.util.ManifestElement; 49 import org.eclipse.osgi.util.NLS; 50 import org.eclipse.pde.core.plugin.IFragmentModel; 51 import org.eclipse.pde.core.plugin.IPluginBase; 52 import org.eclipse.pde.core.plugin.IPluginModelBase; 53 import org.eclipse.pde.core.plugin.PluginRegistry; 54 import org.eclipse.pde.internal.core.AbstractNLModel; 55 import org.eclipse.pde.internal.core.ICoreConstants; 56 import org.eclipse.pde.internal.core.NLResourceHelper; 57 import org.eclipse.pde.internal.core.PDECore; 58 import org.eclipse.pde.internal.core.PDECoreMessages; 59 import org.eclipse.pde.internal.core.TargetPlatformHelper; 60 import org.eclipse.pde.internal.core.ibundle.IBundle; 61 import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase; 62 import org.eclipse.pde.internal.core.ibundle.IManifestHeader; 63 import org.eclipse.pde.internal.core.search.PluginJavaSearchUtil; 64 import org.eclipse.pde.internal.core.util.IdUtil; 65 import org.eclipse.pde.internal.core.util.ManifestUtils; 66 import org.eclipse.pde.internal.core.util.PDEJavaHelper; 67 import org.eclipse.pde.internal.core.util.VersionUtil; 68 import org.osgi.framework.Constants; 69 import org.osgi.framework.InvalidSyntaxException; 70 import org.osgi.framework.Version; 71 72 public class BundleErrorReporter extends JarManifestErrorReporter { 73 74 private boolean fOsgiR4; 75 private IPluginModelBase fModel; 76 private Set fProjectPackages; 77 78 public BundleErrorReporter(IFile file) { 79 super(file); 80 } 81 82 public void validateContent(IProgressMonitor monitor) { 83 super.validateContent(monitor); 84 if (fHeaders == null || getErrorCount() > 0) 85 return; 86 87 fModel = PluginRegistry.findModel(fProject); 88 if (fModel == null || !validateBundleSymbolicName()) 90 return; 91 setOsgiR4(); 92 93 validateFragmentHost(); 94 validateRequiredHeader(Constants.BUNDLE_NAME); 95 validateBundleVersion(); 96 validateRequiredExecutionEnvironment(); 97 98 validateEclipsePlatformFilter(); 99 validateBundleActivator(); 100 validateBundleClasspath(); 101 validateRequireBundle(monitor); 102 validateImportPackage(monitor); 103 validateExportPackage(monitor); 104 validateExportPackages(); 105 validateAutoStart(); 106 validateLazyStart(); 107 validateExtensibleAPI(); 108 validateTranslatableHeaders(); 109 validateImportExportServices(); 110 validateBundleLocalization(); 111 } 112 113 private void validateExportPackages() { 114 IHeader header = getHeader(Constants.EXPORT_PACKAGE); 115 116 if(fModel instanceof IBundlePluginModelBase) { 118 IBundlePluginModelBase bundleModel = (IBundlePluginModelBase) fModel; 119 IBundle bundle = bundleModel.getBundleModel().getBundle(); 120 IManifestHeader bundleClasspathheader = 121 (IManifestHeader) bundle.getManifestHeader(Constants.BUNDLE_CLASSPATH); 122 123 IPackageFragmentRoot[] roots = ManifestUtils.findPackageFragmentRoots(bundleClasspathheader, fProject); 124 StringBuffer packages = new StringBuffer (); 127 for (int i = 0; i < roots.length; i++) { 128 try { 129 if (ManifestUtils.isImmediateRoot(roots[i])) { 130 IJavaElement[] javaElements = roots[i].getChildren(); 131 for (int j = 0; j < javaElements.length; j++) 132 if (javaElements[j] instanceof IPackageFragment) { 133 IPackageFragment fragment = (IPackageFragment) javaElements[j]; 134 String name = fragment.getElementName(); 135 if (name.length() == 0) 136 name = "."; if (fragment.containsJavaResources() || fragment.getNonJavaResources().length > 0){ 138 if (!containsPackage(header, name)) { 139 packages.append(name); 140 if(j < javaElements.length - 1) 141 packages.append(","); 143 } 144 } 145 } 146 } 147 } catch (JavaModelException e) {} 148 } 149 150 if(packages.toString().length() > 0) { 152 IMarker marker = report(PDECoreMessages.BundleErrorReporter_missingPackagesInProject, header == null ? 1 : header.getLineNumber() + 1, 153 CompilerFlags.P_MISSING_EXPORT_PKGS, 154 PDEMarkerFactory.M_MISSING_EXPORT_PKGS, 155 PDEMarkerFactory.CAT_OTHER); 156 try { 157 if (marker != null) 158 marker.setAttribute("packages", packages.toString()); } catch (CoreException e) {} 160 } 161 162 } 163 164 } 165 166 private void setOsgiR4() { 167 IHeader header = getHeader(Constants.BUNDLE_MANIFESTVERSION); 168 if (header != null) { 169 String version = header.getValue(); 170 try { 171 fOsgiR4 = version != null && Integer.parseInt(version) > 1 ; 172 } catch (NumberFormatException e) { 173 } 174 } 175 } 176 177 180 private boolean validateBundleSymbolicName() { 181 IHeader header = validateRequiredHeader(Constants.BUNDLE_SYMBOLICNAME); 182 if (header == null) 183 return false; 184 185 ManifestElement[] elements = header.getElements(); 186 String id = elements.length > 0 ? elements[0].getValue() : null; 187 if (id == null || id.length() == 0) { 188 report(PDECoreMessages.BundleErrorReporter_NoSymbolicName, header.getLineNumber() + 1, 189 CompilerFlags.ERROR, PDEMarkerFactory.CAT_FATAL); 190 return false; 191 } 192 193 validatePluginId(header, id); 194 validateSingleton(header, elements[0]); 195 196 return true; 197 } 198 199 private boolean validatePluginId(IHeader header, String value) { 200 if (!IdUtil.isValidCompositeID(value)) { 201 String message = PDECoreMessages.BundleErrorReporter_InvalidSymbolicName; 202 report(message, getLine(header, value), CompilerFlags.WARNING, PDEMarkerFactory.CAT_FATAL); 203 return false; 204 } 205 return true; 206 } 207 208 private void validateSingleton(IHeader header, ManifestElement element) { 209 String singletonAttr = element.getAttribute(ICoreConstants.SINGLETON_ATTRIBUTE); 210 String singletonDir = element.getDirective(Constants.SINGLETON_DIRECTIVE); 211 IPluginBase base = fModel.getPluginBase(); 212 boolean hasExtensions = base != null && 213 (base.getExtensionPoints().length > 0 214 || base.getExtensions().length > 0); 215 216 if (hasExtensions) { 217 if (TargetPlatformHelper.getTargetVersion() >= 3.1) { 218 if (!"true".equals(singletonDir)) { if ("true".equals(singletonAttr)) { if (isCheckDeprecated()) { 221 String message = PDECoreMessages.BundleErrorReporter_deprecated_attribute_singleton; 222 report(message, getLine(header, ICoreConstants.SINGLETON_ATTRIBUTE + "="), CompilerFlags.P_DEPRECATED, PDEMarkerFactory.M_SINGLETON_DIR_NOT_SET, PDEMarkerFactory.CAT_DEPRECATION); 224 return; 225 } 226 } else { 227 String message = NLS.bind(PDECoreMessages.BundleErrorReporter_singletonRequired, Constants.SINGLETON_DIRECTIVE); 228 report(message, header.getLineNumber() + 1, CompilerFlags.ERROR, PDEMarkerFactory.M_SINGLETON_DIR_NOT_SET, PDEMarkerFactory.CAT_FATAL); 229 return; 230 } 231 } 232 } else if (!"true".equals(singletonAttr)) { String message = NLS.bind(PDECoreMessages.BundleErrorReporter_singletonAttrRequired, 234 ICoreConstants.SINGLETON_ATTRIBUTE); 235 report(message, header.getLineNumber() + 1, CompilerFlags.ERROR, PDEMarkerFactory.M_SINGLETON_ATT_NOT_SET, PDEMarkerFactory.CAT_OTHER); 236 return; 237 } 238 } 239 240 if (TargetPlatformHelper.getTargetVersion() >= 3.1) { 241 if (singletonAttr != null) { 242 if (isCheckDeprecated()) { 243 String message = PDECoreMessages.BundleErrorReporter_deprecated_attribute_singleton; 244 report(message, getLine(header, ICoreConstants.SINGLETON_ATTRIBUTE + "="), CompilerFlags.P_DEPRECATED, PDEMarkerFactory.M_SINGLETON_DIR_NOT_SET, PDEMarkerFactory.CAT_OTHER); 246 } 247 } 248 } else if (singletonDir != null) { 249 if (isCheckDeprecated()) { 250 String message = PDECoreMessages.BundleErrorReporter_unsupportedSingletonDirective; 251 report(message, getLine(header, Constants.SINGLETON_DIRECTIVE + ":="), CompilerFlags.P_DEPRECATED, PDEMarkerFactory.M_SINGLETON_DIR_NOT_SUPPORTED, PDEMarkerFactory.CAT_OTHER); 253 254 } 255 } 256 validateBooleanAttributeValue(header, element, ICoreConstants.SINGLETON_ATTRIBUTE); 257 validateBooleanDirectiveValue(header, element, Constants.SINGLETON_DIRECTIVE); 258 } 259 260 private void validateFragmentHost() { 261 IHeader header = getHeader(Constants.FRAGMENT_HOST); 262 if (header == null) { 263 if (isCheckNoRequiredAttr() && fProject.getFile("fragment.xml").exists()) { report(PDECoreMessages.BundleErrorReporter_HostNeeded, 1, CompilerFlags.P_NO_REQUIRED_ATT, PDEMarkerFactory.CAT_FATAL); 265 } 266 return; 267 } 268 269 if (header.getElements().length == 0) { 270 if (isCheckNoRequiredAttr()) 271 report(PDECoreMessages.BundleErrorReporter_HostNeeded, 1, CompilerFlags.P_NO_REQUIRED_ATT, PDEMarkerFactory.CAT_FATAL); 272 return; 273 } 274 275 if (!isCheckUnresolvedImports()) 276 return; 277 278 BundleDescription desc = fModel.getBundleDescription(); 279 if (desc == null) 280 return; 281 282 HostSpecification host = desc.getHost(); 283 if (host == null) 284 return; 285 286 String name = host.getName(); 287 if (host.getSupplier() == null) { 288 boolean missingHost = false; 289 ResolverError[] errors = desc.getContainingState().getResolverErrors(desc); 290 for (int i = 0; i < errors.length; i++) { 291 if (errors[i].getType() == ResolverError.MISSING_FRAGMENT_HOST) { 292 missingHost = true; 293 break; 294 } 295 } 296 297 if (missingHost) { 298 BundleDescription[] suppliers = desc.getContainingState().getBundles(name); 299 boolean resolved = true; 300 for (int i = 0; i < suppliers.length; i++) { 301 if (suppliers[i].getHost() != null) 302 continue; 303 if (suppliers[i].isResolved()) { 304 Version version = suppliers[i].getVersion(); 305 VersionRange range = host.getVersionRange(); 306 if (!range.isIncluded(version)) { 307 String versionRange = host.getVersionRange().toString(); 308 report(NLS.bind(PDECoreMessages.BundleErrorReporter_BundleRangeInvalidInBundleVersion, versionRange), 309 getLine(header, versionRange), 310 CompilerFlags.P_UNRESOLVED_IMPORTS, 311 PDEMarkerFactory.CAT_FATAL); 312 return; 313 } 314 } else { 315 resolved = false; 316 } 317 } 318 319 if (!resolved) { 320 report(NLS.bind(PDECoreMessages.BundleErrorReporter_unresolvedHost, name), 321 getLine(header, name), CompilerFlags.P_UNRESOLVED_IMPORTS, PDEMarkerFactory.CAT_FATAL); 322 return; 323 } 324 } 325 } 326 327 IPluginModelBase model = PluginRegistry.findModel(name); 328 if (model == null || model instanceof IFragmentModel || !model.isEnabled()) { 329 report(NLS.bind(PDECoreMessages.BundleErrorReporter_HostNotExistPDE, name), 330 getLine(header, name), CompilerFlags.P_UNRESOLVED_IMPORTS, PDEMarkerFactory.CAT_FATAL); 331 } 332 } 333 334 private void validateBundleVersion() { 335 IHeader header = validateRequiredHeader(Constants.BUNDLE_VERSION); 336 if (header == null) 337 return; 338 339 IStatus status = VersionUtil.validateVersion(header.getValue()); 340 if(!status.isOK()){ 341 int line = getLine(header, header.getValue()); 342 report(status.getMessage(), line, CompilerFlags.ERROR, PDEMarkerFactory.CAT_FATAL); 343 } 344 } 345 346 private void validateRequiredExecutionEnvironment() { 347 int sev = CompilerFlags.getFlag(fProject, CompilerFlags.P_INCOMPATIBLE_ENV); 348 if (sev == CompilerFlags.IGNORE) 349 return; 350 BundleDescription desc = fModel.getBundleDescription(); 351 if (desc == null) 352 return; 353 String [] bundleEnvs = desc.getExecutionEnvironments(); 354 if (bundleEnvs == null || bundleEnvs.length == 0) 355 return; 356 357 IHeader header = getHeader(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT); 358 if (header == null) 359 return; 360 361 IExecutionEnvironment env = JavaRuntime.getExecutionEnvironmentsManager().getEnvironment(bundleEnvs[0]); 362 if (env != null) { 363 IJavaProject jproject = JavaCore.create(fProject); 364 IClasspathEntry[] entries; 365 try { 366 entries = jproject.getRawClasspath(); 367 for (int i = 0; i < entries.length; i++) { 368 if (entries[i].getEntryKind() != IClasspathEntry.CPE_CONTAINER) 369 continue; 370 IPath currentPath = entries[i].getPath(); 371 if (JavaRuntime.newDefaultJREContainerPath().matchingFirstSegments(currentPath) == 0) 372 continue; 373 374 IPath validPath = JavaRuntime.newJREContainerPath(env); 375 if (!validPath.equals(currentPath)) { 376 report(NLS.bind(PDECoreMessages.BundleErrorReporter_reqExecEnv_conflict, bundleEnvs[0]), 377 getLine(header, bundleEnvs[0]), 378 sev, PDEMarkerFactory.M_MISMATCHED_EXEC_ENV, 379 PDEMarkerFactory.CAT_EE); 380 } 381 } 382 } catch (JavaModelException e) { 383 } 384 } 385 IExecutionEnvironment[] systemEnvs = JavaRuntime.getExecutionEnvironmentsManager().getExecutionEnvironments(); 386 for (int i = 0; i < bundleEnvs.length; i++) { 387 boolean found = false; 388 for (int j = 0; j < systemEnvs.length; j++) { 389 if (bundleEnvs[i].equals(systemEnvs[j].getId())) { 390 found = true; 391 break; 392 } 393 } 394 if (!found) { 395 report(NLS.bind(PDECoreMessages.BundleErrorReporter_reqExecEnv_unknown, 396 bundleEnvs[i]), getLine(header, bundleEnvs[i]), 397 sev, PDEMarkerFactory.M_UNKNOW_EXEC_ENV, 398 PDEMarkerFactory.CAT_EE); 399 break; 400 } 401 } 402 } 403 404 private void validateEclipsePlatformFilter() { 405 IHeader header = getHeader(ICoreConstants.PLATFORM_FILTER); 406 if (header == null) 407 return; 408 409 try { 410 PDECore.getDefault().getBundleContext().createFilter(header.getValue()); 411 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_INCOMPATIBLE_ENV); 412 if (severity == CompilerFlags.IGNORE) 413 return; 414 BundleDescription desc = fModel.getBundleDescription(); 415 if (desc != null && !desc.isResolved()) { 416 ResolverError[] errors = desc.getContainingState().getResolverErrors(desc); 417 for (int i = 0; i < errors.length; i++) { 418 if (errors[i].getType() == ResolverError.PLATFORM_FILTER) { 419 report(PDECoreMessages.BundleErrorReporter_badFilter, 420 header.getLineNumber() + 1, severity, 421 PDEMarkerFactory.CAT_OTHER); 422 } 423 } 424 } 425 } catch (InvalidSyntaxException ise) { 426 report(PDECoreMessages.BundleErrorReporter_invalidFilterSyntax, 427 header.getLineNumber() + 1, CompilerFlags.ERROR, 428 PDEMarkerFactory.CAT_FATAL); 429 } 430 } 431 432 private void validateBundleActivator() { 433 IHeader header = getHeader(Constants.BUNDLE_ACTIVATOR); 434 if (header == null) 435 return; 436 437 String activator = header.getValue(); 438 BundleDescription desc = fModel.getBundleDescription(); 439 if (desc != null && desc.getHost() != null) { 440 report(PDECoreMessages.BundleErrorReporter_fragmentActivator, 441 header.getLineNumber() + 1, CompilerFlags.ERROR, 442 PDEMarkerFactory.CAT_FATAL); 443 return; 444 } 445 446 if (isCheckUnknownClass()) { 447 try { 448 if (fProject.hasNature(JavaCore.NATURE_ID)) { 449 IJavaProject javaProject = JavaCore.create(fProject); 450 451 if (!PDEJavaHelper.isOnClasspath(activator, javaProject)) { 453 report(NLS.bind(PDECoreMessages.BundleErrorReporter_NoExist, activator), 454 getLine(header, activator), 455 CompilerFlags.P_UNKNOWN_CLASS, 456 PDEMarkerFactory.M_UNKNOWN_ACTIVATOR, 457 PDEMarkerFactory.CAT_FATAL); 458 } 459 } 460 } catch (CoreException ce) { 461 } 462 } 463 } 464 465 private void validateBundleClasspath() { 466 IHeader header = getHeader(Constants.BUNDLE_CLASSPATH); 467 if (header != null && header.getElements().length == 0) { 468 report(PDECoreMessages.BundleErrorReporter_ClasspathNotEmpty, 469 header.getLineNumber() + 1, CompilerFlags.ERROR, 470 PDEMarkerFactory.CAT_FATAL); 471 } 472 } 473 474 private void validateRequireBundle(IProgressMonitor monitor) { 475 if (!isCheckUnresolvedImports()) 476 return; 477 478 IHeader header = getHeader(Constants.REQUIRE_BUNDLE); 479 if (header == null) 480 return; 481 482 BundleDescription desc = fModel.getBundleDescription(); 483 if (desc == null) 484 return; 485 486 ManifestElement[] required = header.getElements(); 487 BundleSpecification[] specs = desc.getRequiredBundles(); 488 for (int i = 0; i < required.length; i++) { 489 checkCanceled(monitor); 490 491 String bundleID = required[i].getValue(); 492 493 validateBundleVersionAttribute(header, required[i]); 494 validateVisibilityDirective(header, required[i]); 495 validateReprovideAttribute(header, required[i]); 496 validateResolutionDirective(header, required[i]); 497 validateOptionalAttribute(header, required[i]); 498 validateFragmentHost(header, required[i]); 499 500 boolean optional = isOptional(required[i]); 501 int severity = getRequireBundleSeverity(required[i], optional); 502 503 if (specs[i].getSupplier() == null) { 504 if (desc.getContainingState().getBundle(specs[i].getName(), null) == null) { 505 IMarker marker = report(NLS.bind(PDECoreMessages.BundleErrorReporter_NotExistPDE, bundleID), 506 getPackageLine(header, required[i]), 507 severity, 508 PDEMarkerFactory.M_REQ_BUNDLE_NOT_AVAILABLE, 509 PDEMarkerFactory.CAT_FATAL); 510 try { 511 if (marker != null) { 512 marker.setAttribute("bundleId", required[i].getValue()); if (optional) 514 marker.setAttribute("optional", true); } 516 } catch (CoreException e) { 517 } 518 } else { 519 report(NLS.bind(PDECoreMessages.BundleErrorReporter_BundleRangeInvalidInBundleVersion, bundleID + ": " + specs[i].getVersionRange()), getPackageLine(header, required[i]), severity, 521 PDEMarkerFactory.CAT_FATAL); 522 } 523 } 524 } 525 } 526 527 private void validateBundleVersionAttribute(IHeader header, ManifestElement element) { 528 String versionRange = element.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE); 529 if (versionRange != null && !VersionUtil.validateVersionRange(versionRange).isOK()) { 530 report(NLS.bind(PDECoreMessages.BundleErrorReporter_InvalidFormatInBundleVersion, 531 element.getValue()), getPackageLine(header, element), 532 CompilerFlags.ERROR, 533 PDEMarkerFactory.CAT_FATAL); 534 } 535 } 536 537 private void validateVisibilityDirective(IHeader header, ManifestElement element) { 538 String visibility = element.getDirective(Constants.VISIBILITY_DIRECTIVE); 539 if (visibility != null) { 540 validateDirectiveValue(header, element,Constants.VISIBILITY_DIRECTIVE, 541 new String [] {Constants.VISIBILITY_PRIVATE, Constants.VISIBILITY_REEXPORT }); 542 } 543 } 544 545 private void validateReprovideAttribute(IHeader header, ManifestElement element) { 546 String message; 547 String rexport = element.getAttribute(ICoreConstants.REPROVIDE_ATTRIBUTE); 548 if (rexport != null) { 549 validateBooleanAttributeValue(header, element,ICoreConstants.REPROVIDE_ATTRIBUTE); 550 if (fOsgiR4 && isCheckDeprecated()) { 551 message = NLS.bind(PDECoreMessages.BundleErrorReporter_deprecated_attribute_reprovide, 552 ICoreConstants.REPROVIDE_ATTRIBUTE); 553 report(message, 554 getLine(header, ICoreConstants.REPROVIDE_ATTRIBUTE + "="), CompilerFlags.P_DEPRECATED, 556 PDEMarkerFactory.CAT_DEPRECATION); 557 } 558 } 559 } 560 561 private boolean isOptional(ManifestElement element) { 562 return Constants.RESOLUTION_OPTIONAL.equals(element.getDirective(Constants.RESOLUTION_DIRECTIVE)) 563 || "true".equals(element.getAttribute(ICoreConstants.OPTIONAL_ATTRIBUTE)); } 565 566 private int getRequireBundleSeverity(ManifestElement requireBundleElement, boolean optional) { 567 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNRESOLVED_IMPORTS); 568 if (optional && severity != CompilerFlags.IGNORE) 569 severity += 1; 570 return severity; 571 } 572 573 private void validateResolutionDirective(IHeader header, 574 ManifestElement requireBundleElement) { 575 String resolution = requireBundleElement 576 .getDirective(Constants.RESOLUTION_DIRECTIVE); 577 if (resolution != null) { 578 validateDirectiveValue(header, requireBundleElement, 579 Constants.RESOLUTION_DIRECTIVE, new String [] { 580 Constants.RESOLUTION_MANDATORY, 581 Constants.RESOLUTION_OPTIONAL }); 582 } 583 } 584 585 private void validateOptionalAttribute(IHeader header, ManifestElement element) { 586 String rexport = element.getAttribute(ICoreConstants.OPTIONAL_ATTRIBUTE); 587 if (rexport != null) { 588 validateBooleanAttributeValue(header, element, ICoreConstants.OPTIONAL_ATTRIBUTE); 589 if (fOsgiR4 && isCheckDeprecated()) { 590 report(NLS.bind(PDECoreMessages.BundleErrorReporter_deprecated_attribute_optional, 591 ICoreConstants.OPTIONAL_ATTRIBUTE), 592 getLine(header, ICoreConstants.OPTIONAL_ATTRIBUTE + "="), CompilerFlags.P_DEPRECATED, 594 PDEMarkerFactory.CAT_DEPRECATION); 595 } 596 } 597 } 598 599 private void validateImportPackage(IProgressMonitor monitor) { 600 BundleDescription desc = fModel.getBundleDescription(); 601 if (desc == null) 602 return; 603 604 IHeader header = getHeader(Constants.IMPORT_PACKAGE); 605 if (header == null) 606 return; 607 608 boolean hasUnresolved = false; 609 VersionConstraint[] constraints = desc.getContainingState().getStateHelper().getUnsatisfiedConstraints(desc); 610 for (int i = 0; i < constraints.length; i++) { 611 if (constraints[i] instanceof ImportPackageSpecification) { 612 hasUnresolved = true; 613 break; 614 } 615 } 616 617 HashMap exported = getAvailableExportedPackages(desc.getContainingState()); 618 619 ImportPackageSpecification[] imports = desc.getImportPackages(); 620 if (desc.hasDynamicImports()) { 621 List staticImportsList = new ArrayList (); 622 for (int i=0;i < imports.length; ++i) { 623 if (! imports[i].getDirective(Constants.RESOLUTION_DIRECTIVE).equals(ImportPackageSpecification.RESOLUTION_DYNAMIC)) 624 staticImportsList.add(imports[i]); 625 } 626 imports = (ImportPackageSpecification[]) staticImportsList.toArray(new ImportPackageSpecification[staticImportsList.size()]); 627 } 628 629 ManifestElement[] elements = header.getElements(); 630 int index = 0; 631 for (int i = 0; i < elements.length; i++) { 632 checkCanceled(monitor); 633 634 validateSpecificationVersionAttribute(header, elements[i]); 635 validateResolutionDirective(header, elements[i]); 636 if (!hasUnresolved) 637 continue; 638 639 validateVersionAttribute(header, elements[i], true); 640 641 int length = elements[i].getValueComponents().length; 642 for (int j = 0; j < length; j++) { 643 ImportPackageSpecification importSpec = imports[index++]; 644 String name = importSpec.getName(); 645 if (name.equals("java") || name.startsWith("java.")) { IHeader jreHeader = getHeader(ICoreConstants.ECLIPSE_JREBUNDLE); 647 if (jreHeader == null || !"true".equals(jreHeader.getValue())) { report(PDECoreMessages.BundleErrorReporter_importNoJRE, getPackageLine(header, elements[i]), CompilerFlags.ERROR, 649 PDEMarkerFactory.M_JAVA_PACKAGE__PORTED, 650 PDEMarkerFactory.CAT_FATAL); 651 continue; 652 } 653 } 654 655 if (importSpec.isResolved() || !isCheckUnresolvedImports()) 656 continue; 657 658 boolean optional = isOptional(elements[i]); 659 int severity = getRequireBundleSeverity(elements[i], optional); 660 661 ExportPackageDescription export = (ExportPackageDescription)exported.get(name); 662 if (export != null) { 663 if (export.getSupplier().isResolved()) { 664 Version version = export.getVersion(); 665 VersionRange range = importSpec.getVersionRange(); 666 if (range != null && !range.isIncluded(version)) { 667 report(NLS.bind(PDECoreMessages.BundleErrorReporter_unsatisfiedConstraint, importSpec.toString()), 668 getPackageLine(header, elements[i]), severity, 669 PDEMarkerFactory.CAT_FATAL); 670 } 671 } else { 672 report(NLS.bind(PDECoreMessages.BundleErrorReporter_unresolvedExporter, 673 new String [] {export.getSupplier().getSymbolicName(), name}), 674 getPackageLine(header, elements[i]), severity, 675 PDEMarkerFactory.CAT_OTHER); 676 } 677 } else { 678 IMarker marker = report(NLS.bind(PDECoreMessages.BundleErrorReporter_PackageNotExported, name), 679 getPackageLine(header, elements[i]), 680 severity, PDEMarkerFactory.M_IMPORT_PKG_NOT_AVAILABLE, 681 PDEMarkerFactory.CAT_FATAL); 682 try { 683 if (marker != null) { 684 marker.setAttribute("packageName", name); if (optional) 686 marker.setAttribute("optional", true); } 688 } catch (CoreException e) { 689 } 690 } 691 } 692 } 693 } 694 695 private HashMap getAvailableExportedPackages(State state) { 696 BundleDescription[] bundles = state.getBundles(); 697 698 HashMap exported = new HashMap (); 699 for (int i = 0; i < bundles.length; i++) { 700 ExportPackageDescription[] exports = bundles[i].getExportPackages(); 701 for (int j = 0; j < exports.length; j++) { 702 String name = exports[j].getName(); 703 if (exported.containsKey(name)) { 704 if (exports[j].getSupplier().isResolved()) { 705 exported.put(name, exports[j]); 706 } 707 } else { 708 exported.put(name, exports[j]); 709 } 710 } 711 } 712 return exported; 713 } 714 715 protected void validateExportPackage(IProgressMonitor monitor) { 716 IHeader header = getHeader(Constants.EXPORT_PACKAGE); 717 if (header == null) 718 return; 719 720 String message = null; 721 ManifestElement[] elements = header.getElements(); 722 723 for (int i = 0; i < elements.length; i++) { 724 checkCanceled(monitor); 725 726 validateVersionAttribute(header, elements[i], false); 727 validateSpecificationVersionAttribute(header,elements[i]); 728 validateX_InternalDirective(header, elements[i]); 729 validateX_FriendsDirective(header, elements[i]); 730 731 String [] valueComps = elements[i].getValueComponents(); 732 for (int j = 0; j < valueComps.length; j++) { 733 String name = valueComps[j]; 734 if (name.equals("java") || name.startsWith("java.")) { IHeader jreHeader = getHeader(ICoreConstants.ECLIPSE_JREBUNDLE); 736 if (jreHeader == null || !"true".equals(jreHeader.getValue())) { message = PDECoreMessages.BundleErrorReporter_exportNoJRE; 738 report(message, getPackageLine(header, elements[i]), 739 CompilerFlags.ERROR, 740 PDEMarkerFactory.M_JAVA_PACKAGE__PORTED, 741 PDEMarkerFactory.CAT_FATAL); 742 } 743 } else if (".".equals(name.trim())) { continue; 746 } 747 748 if (!isCheckUnresolvedImports()) { 749 continue; 750 } 751 752 753 if (!getExportedPackages().contains(name) && !(fProject.getFolder(name.replace('.', '/')).exists())) { 754 message = NLS.bind(PDECoreMessages.BundleErrorReporter_NotExistInProject, name); 755 IMarker marker = report(message, getPackageLine(header, elements[i]), 756 CompilerFlags.P_UNRESOLVED_IMPORTS, 757 PDEMarkerFactory.M_EXPORT_PKG_NOT_EXIST, 758 PDEMarkerFactory.CAT_OTHER); 759 try { 760 if (marker != null) 761 marker.setAttribute("packageName", name); } catch (CoreException e) { 763 } 764 } 765 } 766 } 767 768 } 769 770 private boolean containsPackage(IHeader header, String name) { 771 if(header != null) { 772 ManifestElement[] elements = header.getElements(); 773 for (int i = 0; i < elements.length; i++) { 774 if(elements[i].getValue().equals(name)) 775 return true; 776 } 777 } 778 return false; 779 } 780 781 private Set getExportedPackages() { 782 if (fProjectPackages == null) { 783 fProjectPackages = new HashSet (); 784 addProjectPackages(fProject); 785 BundleDescription desc = fModel.getBundleDescription(); 786 if (desc != null) { 787 HostSpecification host = desc.getHost(); 788 if (host != null) { 789 addHostPackages(host.getName()); 790 } else { 791 addFragmentPackages(desc.getFragments()); 792 } 793 } 794 } 795 return fProjectPackages; 796 } 797 798 private void addHostPackages(String hostID) { 799 IPluginModelBase model = PluginRegistry.findModel(hostID); 800 if (model != null) { 801 IResource resource = model.getUnderlyingResource(); 802 if (resource != null) { 803 addProjectPackages(resource.getProject()); 804 } else { 805 try { 806 if (fProject.hasNature(JavaCore.NATURE_ID)) { 807 IPackageFragment[] packages = PluginJavaSearchUtil.collectPackageFragments( new IPluginModelBase[] { model}, 808 JavaCore.create(fProject), false); 809 for (int i = 0; i < packages.length; i++) 810 fProjectPackages.add(packages[i].getElementName()); 811 } 812 } catch (CoreException ce) { 813 } 814 } 815 } 816 } 817 818 private void addFragmentPackages(BundleDescription[] fragments) { 819 for (int i = 0; i < fragments.length; i++) { 820 String id = fragments[i].getSymbolicName(); 821 IPluginModelBase model = PluginRegistry.findModel(id); 822 IResource resource = model instanceof IFragmentModel ? model.getUnderlyingResource() : null; 823 if (resource != null) { 824 addProjectPackages(resource.getProject()); 825 } 826 } 827 } 828 829 private void addProjectPackages(IProject proj) { 830 try { 831 if (proj.hasNature(JavaCore.NATURE_ID)) { 832 IJavaProject jp = JavaCore.create(proj); 833 IPackageFragmentRoot[] roots = jp.getPackageFragmentRoots(); 834 for (int i = 0; i < roots.length; i++) { 835 if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE 836 || (roots[i].getKind() == IPackageFragmentRoot.K_BINARY && !roots[i].isExternal())) { 837 IJavaElement[] children = roots[i].getChildren(); 838 for (int j = 0; j < children.length; j++) { 839 IPackageFragment f = (IPackageFragment) children[j]; 840 String name = f.getElementName(); 841 if (name.equals("")) name = "."; if (f.hasChildren() || f.getNonJavaResources().length > 0) 844 fProjectPackages.add(name); 845 } 846 } 847 } 848 } 849 } catch (CoreException ce) { 850 } 851 } 852 853 protected boolean isCheckDeprecated() { 854 return CompilerFlags.getFlag(fProject, CompilerFlags.P_DEPRECATED) != CompilerFlags.IGNORE; 855 } 856 857 protected boolean isCheckNoRequiredAttr() { 858 return CompilerFlags.getFlag(fProject, CompilerFlags.P_NO_REQUIRED_ATT) != CompilerFlags.IGNORE; 859 } 860 861 protected boolean isCheckUnknownClass() { 862 return CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_CLASS) != CompilerFlags.IGNORE; 863 } 864 865 protected boolean isCheckUnresolvedImports() { 866 return CompilerFlags.getFlag(fProject, 867 CompilerFlags.P_UNRESOLVED_IMPORTS) != CompilerFlags.IGNORE; 868 } 869 870 private void validateTranslatableHeaders() { 871 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_NOT_EXTERNALIZED); 872 if (severity == CompilerFlags.IGNORE) 873 return; 874 875 for (int i = 0; i < ICoreConstants.TRANSLATABLE_HEADERS.length; i++) { 876 IHeader header = getHeader(ICoreConstants.TRANSLATABLE_HEADERS[i]); 877 if (header != null) { 878 String value = header.getValue(); 879 if (!value.startsWith("%")) { report(NLS.bind(PDECoreMessages.Builders_Manifest_non_ext_attribute, header.getName()), 881 getLine(header, value), 882 severity, 883 PDEMarkerFactory.P_UNTRANSLATED_NODE, header.getName(), 884 PDEMarkerFactory.CAT_NLS); 885 } else if (fModel instanceof AbstractNLModel) { 886 NLResourceHelper helper = ((AbstractNLModel)fModel).getNLResourceHelper(); 887 if (helper == null || !helper.resourceExists(value)) 888 report(NLS.bind(PDECoreMessages.Builders_Manifest_key_not_found, 889 value.substring(1)), getLine(header, value), severity, 890 PDEMarkerFactory.CAT_NLS); 891 } 892 } 893 } 894 } 895 896 private void validateSpecificationVersionAttribute(IHeader header, ManifestElement element) { 897 String version = element.getAttribute(ICoreConstants.PACKAGE_SPECIFICATION_VERSION); 898 IStatus status = VersionUtil.validateVersion(version); 899 if(!status.isOK()){ 900 report(status.getMessage(), getPackageLine(header, element), 901 CompilerFlags.ERROR, 902 PDEMarkerFactory.CAT_FATAL); 903 } 904 if (isCheckDeprecated()) { 905 if (fOsgiR4 && version != null) { 906 report(NLS.bind(PDECoreMessages.BundleErrorReporter_deprecated_attribute_specification_version, 907 ICoreConstants.PACKAGE_SPECIFICATION_VERSION), 908 getPackageLine(header, element), CompilerFlags.P_DEPRECATED, 909 PDEMarkerFactory.CAT_DEPRECATION); 910 } 911 } 912 } 913 914 private void validateVersionAttribute(IHeader header, ManifestElement element, boolean range) { 915 String version = element.getAttribute(Constants.VERSION_ATTRIBUTE); 916 if (version == null) 917 return; 918 IStatus status = range ? VersionUtil.validateVersionRange(version) 919 : VersionUtil.validateVersion(version); 920 if(!status.isOK()) { 921 report(status.getMessage(), getPackageLine(header, element), 922 CompilerFlags.ERROR, 923 PDEMarkerFactory.CAT_FATAL); 924 } 925 } 926 927 private void validateX_InternalDirective(IHeader header, ManifestElement element) { 928 String internal = element.getDirective(ICoreConstants.INTERNAL_DIRECTIVE); 929 if (internal == null) 930 return; 931 932 for (int i = 0; i < BOOLEAN_VALUES.length; i++) { 933 if (BOOLEAN_VALUES[i].equals(internal)) 934 return; 935 } 936 String message = NLS.bind(PDECoreMessages.BundleErrorReporter_dir_value, 937 (new String [] { internal, ICoreConstants.INTERNAL_DIRECTIVE })); 938 report(message, getPackageLine(header, element), CompilerFlags.ERROR, 939 PDEMarkerFactory.CAT_FATAL); 940 } 941 942 private void validateX_FriendsDirective(IHeader header, ManifestElement element) { 943 String friends = element.getDirective(ICoreConstants.FRIENDS_DIRECTIVE); 944 String internal = element.getDirective(ICoreConstants.INTERNAL_DIRECTIVE); 945 if (friends != null && internal != null) { 946 String message = NLS.bind( 947 PDECoreMessages.BundleErrorReporter_directive_hasNoEffectWith_, 948 new String [] { ICoreConstants.FRIENDS_DIRECTIVE, 949 ICoreConstants.INTERNAL_DIRECTIVE }); 950 IMarker marker = report(message, getPackageLine(header, element), 951 CompilerFlags.WARNING, PDEMarkerFactory.M_DIRECTIVE_HAS_NO_EFFECT, 952 PDEMarkerFactory.CAT_OTHER); 953 try { 954 if (marker != null) 955 marker.setAttribute("packageName", element.getValue()); } catch (CoreException e) { 957 } 958 } 959 } 960 961 private void validateAutoStart() { 962 IHeader header = getHeader(ICoreConstants.ECLIPSE_AUTOSTART); 963 if (!validateStartHeader(header)) 964 return; int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_DEPRECATED); 966 if (severity != CompilerFlags.IGNORE && TargetPlatformHelper.getTargetVersion() >= 3.2) { 967 int line = header.getLineNumber(); 968 report(PDECoreMessages.BundleErrorReporter_startHeader_autoStartDeprecated, line + 1, severity, 969 PDEMarkerFactory.M_DEPRECATED_AUTOSTART, 970 PDEMarkerFactory.CAT_DEPRECATION); 971 } 972 } 973 974 private void validateLazyStart() { 975 IHeader header = getHeader(ICoreConstants.ECLIPSE_LAZYSTART); 976 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_DEPRECATED); 977 if (header != null && TargetPlatformHelper.getTargetVersion() < 3.2 && severity != CompilerFlags.IGNORE) { 978 report(PDECoreMessages.BundleErrorReporter_lazyStart_unsupported, 979 header.getLineNumber() + 1, severity, 980 PDEMarkerFactory.NO_RESOLUTION, 981 PDEMarkerFactory.CAT_OTHER); 982 } else { 983 validateStartHeader(header); 984 } 985 } 986 987 private boolean validateStartHeader(IHeader header) { 988 if (header == null) 989 return false; 990 validateBooleanValue(header); 991 return exceptionsAttributesValid(header, header.getElements()); 992 } 993 994 private boolean exceptionsAttributesValid(IHeader header, ManifestElement[] elements) { 995 if (elements == null || elements.length == 0) 996 return true; 997 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_ATTRIBUTE); 998 if (severity == CompilerFlags.IGNORE) 999 return true; 1000 Enumeration keys = elements[0].getKeys(); 1001 if (keys != null && keys.hasMoreElements()) { 1002 String key = (String ) keys.nextElement(); 1003 if ("exceptions".equals(key)) { String [] values = elements[0].getAttributes(key); 1005 for (int i = 0; i < values.length; i++) { 1006 StringTokenizer st = new StringTokenizer (values[i], ","); while (st.hasMoreTokens()) { 1008 String name = st.nextToken().trim(); 1009 if (!getExportedPackages().contains(name)) { 1010 String message = NLS.bind(PDECoreMessages.BundleErrorReporter_NotExistInProject, name); 1011 report(message, getLine(header, name), CompilerFlags.P_UNRESOLVED_IMPORTS, PDEMarkerFactory.CAT_OTHER); 1012 return false; 1013 } 1014 } 1015 } 1016 } 1017 } 1018 return true; 1019 } 1020 1021 private void validateExtensibleAPI(){ 1022 IHeader header = getHeader(ICoreConstants.EXTENSIBLE_API); 1023 if (header != null) 1024 validateBooleanValue(header); 1025 } 1026 1027 public void report(String message, int line, int severity, int problemID, String headerName, String category) { 1028 try { 1029 IMarker marker = report(message, line, severity, problemID, category); 1030 if (marker != null) 1031 marker.setAttribute(PDEMarkerFactory.MPK_LOCATION_PATH, headerName); 1032 } catch (CoreException e) { 1033 } 1034 } 1035 1036 1037 private void validateImportExportServices() { 1038 if(fOsgiR4) { 1039 IHeader importHeader = getHeader(ICoreConstants.IMPORT_SERVICE); 1040 IHeader exportHeader = getHeader(ICoreConstants.EXPORT_SERVICE); 1041 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_DEPRECATED); 1042 1043 if (severity == CompilerFlags.IGNORE) 1044 return; 1045 1046 if(importHeader != null) { 1047 int line = importHeader.getLineNumber(); 1048 report(NLS.bind(PDECoreMessages.BundleErrorReporter_importexport_servicesDeprecated, ICoreConstants.IMPORT_SERVICE), 1049 line + 1, severity, 1050 PDEMarkerFactory.M_DEPRECATED_IMPORT_SERVICE, 1051 PDEMarkerFactory.CAT_DEPRECATION); 1052 } 1053 1054 if (exportHeader != null) { 1055 int line = exportHeader.getLineNumber(); 1056 report(NLS.bind(PDECoreMessages.BundleErrorReporter_importexport_servicesDeprecated, ICoreConstants.EXPORT_SERVICE), 1057 line + 1, severity, 1058 PDEMarkerFactory.M_DEPRECATED_EXPORT_SERVICE, 1059 PDEMarkerFactory.CAT_DEPRECATION); 1060 } 1061 } 1062 } 1063 1064 private void validateBundleLocalization() { 1065 IHeader header = getHeader(Constants.BUNDLE_LOCALIZATION); 1066 if (header == null) 1067 return; 1068 String location = header.getValue(); 1069 String fileName = null; 1070 int index = location.lastIndexOf('/'); 1071 if (index > 0) { 1072 fileName = location.substring(index + 1); 1073 location = location.substring(0, index); 1074 } else { 1075 fileName = location; 1076 location = new String (); 1077 } 1078 1079 IResource res = fProject.findMember(location); 1080 if (res == null || !(res instanceof IContainer)) { 1081 report(PDECoreMessages.BundleErrorReporter_localization_folder_not_exist, header.getLineNumber() + 1, 1082 CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_RESOURCE), PDEMarkerFactory.CAT_OTHER); 1083 return; 1084 } 1085 IContainer folder = (IContainer)res; 1086 try { 1087 IResource[] children = folder.members(); 1088 for (int i = 0; i < children.length; i++) { 1089 if (!(children[i] instanceof IFile)) 1090 continue; 1091 String childName = children[i].getName(); 1092 if (childName.endsWith(".properties") && childName.startsWith(fileName)) return; 1094 } 1095 } catch (CoreException e) { 1096 } 1097 report(PDECoreMessages.BundleErrorReporter_localization_properties_file_not_exist, header.getLineNumber() + 1, 1098 CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_RESOURCE), PDEMarkerFactory.CAT_OTHER); 1099 } 1100 1101 private void validateFragmentHost(IHeader requireBundleHeader, ManifestElement element) { 1102 IHeader header = getHeader(Constants.FRAGMENT_HOST); 1103 if(header == null) 1104 return; 1105 1106 ManifestElement[] elements = header.getElements(); 1107 1108 if (header != null && elements[0] != null && elements[0].getValue().equals(element.getValue())) { 1109 IMarker marker = report(NLS.bind(PDECoreMessages.BundleErrorReporter_unecessaryDependencyDueToFragmentHost, element.getValue()), 1110 getPackageLine(requireBundleHeader, element), CompilerFlags.WARNING, 1111 PDEMarkerFactory.M_UNECESSARY_DEP, 1112 PDEMarkerFactory.CAT_OTHER); 1113 if (marker != null) { 1114 try { 1115 marker.setAttribute("bundleId", element.getValue()); } catch (CoreException e) {} 1117 } 1118 } 1119 } 1120} | Popular Tags |