blob: 44bba2abb1c1512d151e7a162406a64d22a61b83 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.internal.core.builders;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.PluginVersionIdentifier;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.ExportPackageDescription;
import org.eclipse.osgi.service.resolver.HostSpecification;
import org.eclipse.osgi.service.resolver.ImportPackageSpecification;
import org.eclipse.osgi.service.resolver.ResolverError;
import org.eclipse.osgi.service.resolver.State;
import org.eclipse.osgi.service.resolver.VersionConstraint;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.core.plugin.IFragmentModel;
import org.eclipse.pde.core.plugin.IPluginBase;
import org.eclipse.pde.core.plugin.IPluginModel;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.internal.core.AbstractModel;
import org.eclipse.pde.internal.core.ICoreConstants;
import org.eclipse.pde.internal.core.ModelEntry;
import org.eclipse.pde.internal.core.NLResourceHelper;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.PDECoreMessages;
import org.eclipse.pde.internal.core.PluginModelManager;
import org.eclipse.pde.internal.core.TargetPlatform;
import org.eclipse.pde.internal.core.search.PluginJavaSearchUtil;
import org.eclipse.pde.internal.core.util.IdUtil;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;
public class BundleErrorReporter extends JarManifestErrorReporter {
/**
* @param versionString
* the version to be checked, null is allowed and will be treated
* as 0.0.0
* @return IStatus
*/
protected static IStatus validateVersionString(String versionString) {
if (versionString == null)
return Status.OK_STATUS;
return PluginVersionIdentifier.validateVersion(versionString);
}
protected static IStatus validateVersionRange(String versionRangeString) {
try {
new VersionRange(versionRangeString);
} catch (IllegalArgumentException e) {
return new Status(IStatus.ERROR, PDECore.PLUGIN_ID, IStatus.ERROR,
PDECoreMessages.BundleErrorReporter_invalidVersionRangeFormat, e);
}
// need to do our extra checks for each piece of the versionRange
int comma = versionRangeString.indexOf(',');
if (comma < 0) {
return validateVersionString(versionRangeString);
}
IStatus status = validateVersionString(versionRangeString.substring(1, comma));
if(!status.isOK()){
return status;
}
return validateVersionString(versionRangeString
.substring(comma + 1, versionRangeString.length() - 1));
}
private boolean fOsgiR4;
private IPluginModelBase fModel;
private Set fProjectPackages;
public BundleErrorReporter(IFile file) {
super(file);
}
public void validateContent(IProgressMonitor monitor) {
super.validateContent(monitor);
if (fHeaders == null || getErrorCount() > 0)
return;
fModel = PDECore.getDefault().getModelManager().findModel(fProject);
setOsgiR4();
if (!validateBundleSymbolicName())
return;
validateFragmentHost();
validateRequiredHeader(Constants.BUNDLE_NAME);
validateBundleVersion();
validateEclipsePlatformFilter();
validateBundleActivator();
validateBundleClasspath();
validateRequireBundle(monitor);
validateImportPackage(monitor);
validateExportPackage(monitor);
validateAutoStart();
validateLazyStart();
validateExtensibleAPI();
validateTranslatableHeaders();
}
private void setOsgiR4() {
IHeader header = (IHeader) fHeaders.get(Constants.BUNDLE_MANIFESTVERSION);
if (header != null) {
String version = header.getValue();
try {
fOsgiR4 = version != null && Integer.parseInt(version) > 1 ;
} catch (NumberFormatException e) {
}
}
}
/**
* @return boolean false if fatal
*/
private boolean validateBundleSymbolicName() {
IHeader header = validateRequiredHeader(Constants.BUNDLE_SYMBOLICNAME);
if (header == null)
return false;
ManifestElement[] elements = header.getElements();
String id = elements.length > 0 ? elements[0].getValue() : null;
if (id == null || id.length() == 0) {
report(PDECoreMessages.BundleErrorReporter_NoSymbolicName, header.getLineNumber() + 1, CompilerFlags.ERROR);
return false;
}
validatePluginId(header, id);
validateSingleton(header, elements[0]);
return true;
}
private boolean validatePluginId(IHeader header, String value) {
if (!IdUtil.isValidCompositeID(value)) {
String message = PDECoreMessages.BundleErrorReporter_InvalidSymbolicName;
report(message, getLine(header, value), CompilerFlags.WARNING);
return false;
}
return true;
}
private void validateSingleton(IHeader header, ManifestElement element) {
String singletonAttr = element.getAttribute(ICoreConstants.SINGLETON_ATTRIBUTE);
String singletonDir = element.getDirective(Constants.SINGLETON_DIRECTIVE);
IPluginBase base = fModel.getPluginBase();
boolean hasExtensions = base != null &&
(base.getExtensionPoints().length > 0
|| base.getExtensions().length > 0);
if (hasExtensions) {
if (TargetPlatform.getTargetVersion() >= 3.1) {
if (!"true".equals(singletonDir)) { //$NON-NLS-1$
if ("true".equals(singletonAttr)) { //$NON-NLS-1$
if (isCheckDeprecated()) {
String message = PDECoreMessages.BundleErrorReporter_deprecated_attribute_singleton;
report(message, getLine(header, ICoreConstants.SINGLETON_ATTRIBUTE + "="), //$NON-NLS-1$
CompilerFlags.P_DEPRECATED, PDEMarkerFactory.M_SINGLETON_DIR_NOT_SET);
return;
}
} else {
String message = NLS.bind(PDECoreMessages.BundleErrorReporter_singletonRequired, Constants.SINGLETON_DIRECTIVE);
report(message, header.getLineNumber() + 1, CompilerFlags.ERROR, PDEMarkerFactory.M_SINGLETON_DIR_NOT_SET);
return;
}
}
} else if (!"true".equals(singletonAttr)) { //$NON-NLS-1$
String message = NLS.bind(PDECoreMessages.BundleErrorReporter_singletonAttrRequired,
ICoreConstants.SINGLETON_ATTRIBUTE);
report(message, header.getLineNumber() + 1, CompilerFlags.ERROR, PDEMarkerFactory.M_SINGLETON_ATT_NOT_SET);
return;
}
}
if (TargetPlatform.getTargetVersion() >= 3.1) {
if (singletonAttr != null) {
if (isCheckDeprecated()) {
String message = PDECoreMessages.BundleErrorReporter_deprecated_attribute_singleton;
report(message, getLine(header, ICoreConstants.SINGLETON_ATTRIBUTE + "="), //$NON-NLS-1$
CompilerFlags.P_DEPRECATED, PDEMarkerFactory.M_SINGLETON_DIR_NOT_SET);
}
}
} else if (singletonDir != null) {
if (isCheckDeprecated()) {
String message = PDECoreMessages.BundleErrorReporter_unsupportedSingletonDirective;
report(message, getLine(header, Constants.SINGLETON_DIRECTIVE + ":="), //$NON-NLS-1$
CompilerFlags.P_DEPRECATED, PDEMarkerFactory.M_SINGLETON_DIR_NOT_SUPPORTED);
}
}
validateBooleanAttributeValue(header, element, ICoreConstants.SINGLETON_ATTRIBUTE);
validateBooleanDirectiveValue(header, element, Constants.SINGLETON_DIRECTIVE);
}
private void validateFragmentHost() {
IHeader header = (IHeader) fHeaders.get(Constants.FRAGMENT_HOST);
if (header == null) {
if (isCheckNoRequiredAttr() && fProject.getFile("fragment.xml").exists()) { //$NON-NLS-1$
report(PDECoreMessages.BundleErrorReporter_HostNeeded, 1, CompilerFlags.P_NO_REQUIRED_ATT);
}
return;
}
if (header.getElements().length == 0) {
if (isCheckNoRequiredAttr())
report(PDECoreMessages.BundleErrorReporter_HostNeeded, 1, CompilerFlags.P_NO_REQUIRED_ATT);
return;
}
if (!isCheckUnresolvedImports())
return;
BundleDescription desc = fModel.getBundleDescription();
if (desc == null)
return;
HostSpecification host = desc.getHost();
if (host == null)
return;
String name = host.getName();
if (host.getSupplier() == null) {
boolean missingHost = false;
ResolverError[] errors = desc.getContainingState().getResolverErrors(desc);
for (int i = 0; i < errors.length; i++) {
if (errors[i].getType() == ResolverError.MISSING_FRAGMENT_HOST) {
missingHost = true;
break;
}
}
if (missingHost) {
BundleDescription[] suppliers = desc.getContainingState().getBundles(name);
boolean resolved = true;
for (int i = 0; i < suppliers.length; i++) {
if (suppliers[i].getHost() != null)
continue;
if (suppliers[i].isResolved()) {
Version version = suppliers[i].getVersion();
VersionRange range = host.getVersionRange();
if (!range.isIncluded(version)) {
String versionRange = host.getVersionRange().toString();
report(NLS.bind(PDECoreMessages.BundleErrorReporter_BundleRangeInvalidInBundleVersion, versionRange),
getLine(header, versionRange),
CompilerFlags.P_UNRESOLVED_IMPORTS);
return;
}
} else {
resolved = false;
}
}
if (!resolved) {
report(NLS.bind(PDECoreMessages.BundleErrorReporter_unresolvedHost, name),
getLine(header, name), CompilerFlags.P_UNRESOLVED_IMPORTS);
return;
}
}
}
ModelEntry entry = PDECore.getDefault().getModelManager().findEntry(name);
IPluginModelBase model = entry == null ? null : entry.getActiveModel();
if (model == null || model instanceof IFragmentModel || !model.isEnabled()) {
report(NLS.bind(PDECoreMessages.BundleErrorReporter_HostNotExistPDE, name),
getLine(header, name), CompilerFlags.P_UNRESOLVED_IMPORTS);
}
}
private void validateBundleVersion() {
IHeader header = validateRequiredHeader(Constants.BUNDLE_VERSION);
if (header == null)
return;
IStatus status = validateVersionString(header.getValue());
if(!status.isOK()){
int line = getLine(header, header.getValue());
report(status.getMessage(), line, CompilerFlags.ERROR);
}
}
private void validateEclipsePlatformFilter() {
IHeader header = (IHeader) fHeaders.get(ICoreConstants.PLATFORM_FILTER);
if (header == null)
return;
try {
PDECore.getDefault().getBundleContext().createFilter(header.getValue());
int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_INCOMPATIBLE_ENV);
if (severity == CompilerFlags.IGNORE)
return;
BundleDescription desc = fModel.getBundleDescription();
if (desc != null && !desc.isResolved()) {
ResolverError[] errors = desc.getContainingState().getResolverErrors(desc);
for (int i = 0; i < errors.length; i++) {
if (errors[i].getType() == ResolverError.PLATFORM_FILTER) {
report(PDECoreMessages.BundleErrorReporter_badFilter,
header.getLineNumber() + 1, severity);
}
}
}
} catch (InvalidSyntaxException ise) {
report(PDECoreMessages.BundleErrorReporter_invalidFilterSyntax,
header.getLineNumber() + 1, CompilerFlags.ERROR);
}
}
private void validateBundleActivator() {
IHeader header = (IHeader) fHeaders.get(Constants.BUNDLE_ACTIVATOR);
if (header == null)
return;
String activator = header.getValue();
BundleDescription desc = fModel.getBundleDescription();
if (desc != null && desc.getHost() != null) {
report(PDECoreMessages.BundleErrorReporter_fragmentActivator, header.getLineNumber() + 1, CompilerFlags.ERROR);
return;
}
if (isCheckUnknownClass()) {
try {
if (fProject.hasNature(JavaCore.NATURE_ID)) {
IJavaProject javaProject = JavaCore.create(fProject);
if (activator.indexOf('$') != -1)
activator = activator.replace('$', '.');
// Look for this activator in the project's classpath
IType type = javaProject.findType(activator);
if (type == null || !type.exists()) {
report(NLS.bind(PDECoreMessages.BundleErrorReporter_NoExist, activator),
getLine(header, activator),
CompilerFlags.P_UNKNOWN_CLASS,
PDEMarkerFactory.M_UNKNOWN_ACTIVATOR);
}
}
} catch (CoreException ce) {
}
}
}
private void validateBundleClasspath() {
IHeader header = (IHeader) fHeaders.get(Constants.BUNDLE_CLASSPATH);
if (header != null && header.getElements().length == 0) {
report(PDECoreMessages.BundleErrorReporter_ClasspathNotEmpty, header.getLineNumber() + 1, CompilerFlags.ERROR);
}
}
private void validateRequireBundle(IProgressMonitor monitor) {
if (!isCheckUnresolvedImports())
return;
IHeader header = (IHeader) fHeaders.get(Constants.REQUIRE_BUNDLE);
if (header == null)
return;
ManifestElement[] required = header.getElements();
for (int i = 0; i < required.length; i++) {
checkCanceled(monitor);
String bundleID = required[i].getValue();
validateBundleVersionAttribute(header, required[i]);
validateVisibilityDirective(header, required[i]);
validateReprovideAttribute(header, required[i]);
validateResolutionDirective(header, required[i]);
validateOptionalAttribute(header, required[i]);
boolean optional = isOptional(required[i]);
int severity = getRequireBundleSeverity(required[i], optional);
IPluginModel model = PDECore.getDefault().getModelManager().findPluginModel(bundleID);
if (model == null || !model.isEnabled()) {
IMarker marker = report(NLS.bind(PDECoreMessages.BundleErrorReporter_NotExistPDE, bundleID),
getPackageLine(header, required[i]),
severity, PDEMarkerFactory.M_REQ_BUNDLE_NOT_AVAILABLE);
try {
if (marker != null) {
marker.setAttribute("bundleId", required[i].getValue()); //$NON-NLS-1$
if (optional)
marker.setAttribute("optional", true); //$NON-NLS-1$
}
} catch (CoreException e) {
}
continue;
}
String requiredRange = required[i].getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE);
if (requiredRange != null && validateVersionRange(requiredRange).isOK()) {
VersionRange versionRange = new VersionRange(requiredRange);
String version = model.getPlugin().getVersion();
if (version != null && !versionRange.isIncluded(new Version(version))) {
report(NLS.bind(PDECoreMessages.BundleErrorReporter_BundleRangeInvalidInBundleVersion, bundleID + ": " + versionRange.toString()), //$NON-NLS-1$
getPackageLine(header, required[i]), severity);
}
}
}
}
private void validateBundleVersionAttribute(IHeader header, ManifestElement element) {
String versionRange = element.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE);
if (versionRange != null && !validateVersionRange(versionRange).isOK()) {
report(NLS.bind(PDECoreMessages.BundleErrorReporter_InvalidFormatInBundleVersion,
element.getValue()), getPackageLine(header, element),
CompilerFlags.ERROR);
}
}
private void validateVisibilityDirective(IHeader header, ManifestElement element) {
String visibility = element.getDirective(Constants.VISIBILITY_DIRECTIVE);
if (visibility != null) {
validateDirectiveValue(header, element,Constants.VISIBILITY_DIRECTIVE,
new String[] {Constants.VISIBILITY_PRIVATE, Constants.VISIBILITY_REEXPORT });
}
}
private void validateReprovideAttribute(IHeader header, ManifestElement element) {
String message;
String rexport = element.getAttribute(ICoreConstants.REPROVIDE_ATTRIBUTE);
if (rexport != null) {
validateBooleanAttributeValue(header, element,ICoreConstants.REPROVIDE_ATTRIBUTE);
if (fOsgiR4 && isCheckDeprecated()) {
message = NLS.bind(PDECoreMessages.BundleErrorReporter_deprecated_attribute_reprovide,
ICoreConstants.REPROVIDE_ATTRIBUTE);
report(message,
getLine(header, ICoreConstants.REPROVIDE_ATTRIBUTE + "="), //$NON-NLS-1$
CompilerFlags.P_DEPRECATED); //$NON-NLS-1$
}
}
}
private boolean isOptional(ManifestElement element) {
return Constants.RESOLUTION_OPTIONAL.equals(element.getDirective(Constants.RESOLUTION_DIRECTIVE))
|| "true".equals(element.getAttribute(ICoreConstants.OPTIONAL_ATTRIBUTE)); //$NON-NLS-1$
}
private int getRequireBundleSeverity(ManifestElement requireBundleElement, boolean optional) {
int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNRESOLVED_IMPORTS);
if (optional && severity != CompilerFlags.IGNORE)
severity += 1;
return severity;
}
private void validateResolutionDirective(IHeader header,
ManifestElement requireBundleElement) {
String resolution = requireBundleElement
.getDirective(Constants.RESOLUTION_DIRECTIVE);
if (resolution != null) {
validateDirectiveValue(header, requireBundleElement,
Constants.RESOLUTION_DIRECTIVE, new String[] {
Constants.RESOLUTION_MANDATORY,
Constants.RESOLUTION_OPTIONAL });
}
}
private void validateOptionalAttribute(IHeader header, ManifestElement element) {
String rexport = element.getAttribute(ICoreConstants.OPTIONAL_ATTRIBUTE);
if (rexport != null) {
validateBooleanAttributeValue(header, element, ICoreConstants.OPTIONAL_ATTRIBUTE);
if (fOsgiR4 && isCheckDeprecated()) {
report(NLS.bind(PDECoreMessages.BundleErrorReporter_deprecated_attribute_optional,
ICoreConstants.OPTIONAL_ATTRIBUTE),
getLine(header, ICoreConstants.OPTIONAL_ATTRIBUTE + "="), //$NON-NLS-1$
CompilerFlags.P_DEPRECATED);
}
}
}
private void validateImportPackage(IProgressMonitor monitor) {
BundleDescription desc = fModel.getBundleDescription();
if (desc == null)
return;
IHeader header = (IHeader) fHeaders.get(Constants.IMPORT_PACKAGE);
if (header == null)
return;
boolean hasUnresolved = false;
VersionConstraint[] constraints = desc.getContainingState().getStateHelper().getUnsatisfiedConstraints(desc);
for (int i = 0; i < constraints.length; i++) {
if (constraints[i] instanceof ImportPackageSpecification) {
hasUnresolved = true;
break;
}
}
if (!hasUnresolved)
return;
HashMap exported = getAvailableExportedPackages(desc.getContainingState());
ImportPackageSpecification[] imports = desc.getImportPackages();
ManifestElement[] elements = header.getElements();
for (int i = 0; i < elements.length; i++) {
checkCanceled(monitor);
validateSpecificationVersionAttribute(header, elements[i]);
validateVersionAttribute(header, elements[i], true);
validateResolutionDirective(header, elements[i]);
String name = imports[i].getName();
if (name.equals("java") || name.startsWith("java.")) { //$NON-NLS-1$ //$NON-NLS-2$
IHeader jreHeader = (IHeader)fHeaders.get(ICoreConstants.ECLIPSE_JREBUNDLE);
if (jreHeader == null || !"true".equals(jreHeader.getValue())) { //$NON-NLS-1$
report(PDECoreMessages.BundleErrorReporter_importNoJRE, getPackageLine(header, elements[i]), CompilerFlags.ERROR, PDEMarkerFactory.M_JAVA_PACKAGE__PORTED);
continue;
}
}
if (imports[i].isResolved() || !isCheckUnresolvedImports())
continue;
boolean optional = isOptional(elements[i]);
int severity = getRequireBundleSeverity(elements[i], optional);
ExportPackageDescription export = (ExportPackageDescription)exported.get(name);
if (export != null) {
if (export.getSupplier().isResolved()) {
report(NLS.bind(PDECoreMessages.BundleErrorReporter_unsatisfiedConstraint, imports[i].toString()),
getPackageLine(header, elements[i]), severity);
} else {
report(NLS.bind(PDECoreMessages.BundleErrorReporter_unresolvedExporter,
new String[] {export.getSupplier().getSymbolicName(), name}),
getPackageLine(header, elements[i]), severity);
}
} else {
IMarker marker = report(NLS.bind(PDECoreMessages.BundleErrorReporter_PackageNotExported, name),
getPackageLine(header, elements[i]),
severity, PDEMarkerFactory.M_IMPORT_PKG_NOT_AVAILABLE);
try {
if (marker != null) {
marker.setAttribute("packageName", name); //$NON-NLS-1$
if (optional)
marker.setAttribute("optional", true); //$NON-NLS-1$
}
} catch (CoreException e) {
}
}
}
}
private HashMap getAvailableExportedPackages(State state) {
BundleDescription[] bundles = state.getBundles();
HashMap exported = new HashMap();
for (int i = 0; i < bundles.length; i++) {
ExportPackageDescription[] exports = bundles[i].getExportPackages();
for (int j = 0; j < exports.length; j++) {
String name = exports[j].getName();
if (exported.containsKey(name)) {
if (exports[j].getSupplier().isResolved()) {
exported.put(name, exports[j]);
}
} else {
exported.put(name, exports[j]);
}
}
}
return exported;
}
protected void validateExportPackage(IProgressMonitor monitor) {
IHeader header = (IHeader) fHeaders.get(Constants.EXPORT_PACKAGE);
if (header == null)
return;
String message = null;
ManifestElement[] elements = header.getElements();
for (int i = 0; i < elements.length; i++) {
checkCanceled(monitor);
validateVersionAttribute(header, elements[i], false);
validateSpecificationVersionAttribute(header,elements[i]);
validateX_InternalDirective(header, elements[i]);
validateX_FriendsDirective(header, elements[i]);
String name = elements[i].getValue();
if (name.equals("java") || name.startsWith("java.")) { //$NON-NLS-1$ //$NON-NLS-2$
IHeader jreHeader = (IHeader)fHeaders.get(ICoreConstants.ECLIPSE_JREBUNDLE);
if (jreHeader == null || !"true".equals(jreHeader.getValue())) { //$NON-NLS-1$
message = PDECoreMessages.BundleErrorReporter_exportNoJRE;
report(message, getPackageLine(header, elements[i]), CompilerFlags.ERROR, PDEMarkerFactory.M_JAVA_PACKAGE__PORTED);
}
} else if (".".equals(name.trim())) { //$NON-NLS-1$
// workaround for manifest converter generating "."
continue;
}
if (!isCheckUnresolvedImports()) {
continue;
}
/* The exported package does not exist in the bundle */
if (!getExportedPackages().contains(name)) {
message = NLS.bind(PDECoreMessages.BundleErrorReporter_NotExistInProject, name);
IMarker marker = report(message, getPackageLine(header, elements[i]),
CompilerFlags.P_UNRESOLVED_IMPORTS, PDEMarkerFactory.M_EXPORT_PKG_NOT_EXIST);
try {
if (marker != null)
marker.setAttribute("packageName", name); //$NON-NLS-1$
} catch (CoreException e) {
}
}
}
}
private Set getExportedPackages() {
if (fProjectPackages == null) {
fProjectPackages = new HashSet();
addProjectPackages(fProject);
BundleDescription desc = fModel.getBundleDescription();
if (desc != null) {
HostSpecification host = desc.getHost();
if (host != null) {
addHostPackages(host.getName());
} else {
addFragmentPackages(desc.getFragments());
}
}
}
return fProjectPackages;
}
private void addHostPackages(String hostID) {
PluginModelManager manager = PDECore.getDefault().getModelManager();
IPluginModel model = manager.findPluginModel(hostID);
if (model != null) {
IResource resource = model.getUnderlyingResource();
if (resource != null) {
addProjectPackages(resource.getProject());
} else {
try {
if (fProject.hasNature(JavaCore.NATURE_ID)) {
IPackageFragment[] packages = PluginJavaSearchUtil.collectPackageFragments( new IPluginBase[] { model
.getPluginBase() },
JavaCore.create(fProject), false);
for (int i = 0; i < packages.length; i++)
fProjectPackages.add(packages[i].getElementName());
}
} catch (CoreException ce) {
}
}
}
}
private void addFragmentPackages(BundleDescription[] fragments) {
PluginModelManager manager = PDECore.getDefault().getModelManager();
for (int i = 0; i < fragments.length; i++) {
String id = fragments[i].getSymbolicName();
IFragmentModel model = manager.findFragmentModel(id);
IResource resource = model == null ? null : model.getUnderlyingResource();
if (resource != null) {
addProjectPackages(resource.getProject());
}
}
}
private void addProjectPackages(IProject proj) {
try {
if (proj.hasNature(JavaCore.NATURE_ID)) {
IJavaProject jp = JavaCore.create(proj);
IPackageFragmentRoot[] roots = jp.getPackageFragmentRoots();
for (int i = 0; i < roots.length; i++) {
if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE
|| (roots[i].getKind() == IPackageFragmentRoot.K_BINARY && !roots[i].isExternal())) {
IJavaElement[] children = roots[i].getChildren();
for (int j = 0; j < children.length; j++) {
IPackageFragment f = (IPackageFragment) children[j];
String name = f.getElementName();
if (name.equals("")) //$NON-NLS-1$
name = "."; //$NON-NLS-1$
if (f.hasChildren() || f.getNonJavaResources().length > 0)
fProjectPackages.add(name);
}
}
}
}
} catch (CoreException ce) {
}
}
protected boolean isCheckDeprecated() {
return CompilerFlags.getFlag(fProject, CompilerFlags.P_DEPRECATED) != CompilerFlags.IGNORE;
}
protected boolean isCheckNoRequiredAttr() {
return CompilerFlags.getFlag(fProject, CompilerFlags.P_NO_REQUIRED_ATT) != CompilerFlags.IGNORE;
}
protected boolean isCheckUnknownClass() {
return CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_CLASS) != CompilerFlags.IGNORE;
}
protected boolean isCheckUnresolvedImports() {
return CompilerFlags.getFlag(fProject,
CompilerFlags.P_UNRESOLVED_IMPORTS) != CompilerFlags.IGNORE;
}
private void validateTranslatableHeaders() {
int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_NOT_EXTERNALIZED);
if (severity == CompilerFlags.IGNORE)
return;
for (int i = 0; i < ICoreConstants.TRANSLATABLE_HEADERS.length; i++) {
IHeader header = (IHeader) fHeaders.get(ICoreConstants.TRANSLATABLE_HEADERS[i]);
if (header != null) {
String value = header.getValue();
if (!value.startsWith("%")) { //$NON-NLS-1$
report(NLS.bind(PDECoreMessages.Builders_Manifest_non_ext_attribute, header.getName()),
getLine(header, value),
severity,
PDEMarkerFactory.P_UNTRANSLATED_NODE, header.getName());
} else if (fModel instanceof AbstractModel) {
NLResourceHelper helper = ((AbstractModel)fModel).getNLResourceHelper();
if (helper == null || !helper.resourceExists(value))
report(NLS.bind(PDECoreMessages.Builders_Manifest_key_not_found, value.substring(1)), getLine(header, value), severity);
}
}
}
}
private void validateSpecificationVersionAttribute(IHeader header, ManifestElement element) {
String version = element.getAttribute(ICoreConstants.PACKAGE_SPECIFICATION_VERSION);
IStatus status = validateVersionString(version);
if(!status.isOK()){
report(status.getMessage(), getPackageLine(header, element), CompilerFlags.ERROR);
}
if (isCheckDeprecated()) {
if (fOsgiR4 && version != null) {
report(NLS.bind(PDECoreMessages.BundleErrorReporter_deprecated_attribute_specification_version,
ICoreConstants.PACKAGE_SPECIFICATION_VERSION),
getPackageLine(header, element), CompilerFlags.P_DEPRECATED);
}
}
}
private void validateVersionAttribute(IHeader header, ManifestElement element, boolean range) {
String version = element.getAttribute(Constants.VERSION_ATTRIBUTE);
if (version == null)
return;
IStatus status = range ? validateVersionRange(version) : validateVersionString(version);
if(!status.isOK()) {
report(status.getMessage(), getPackageLine(header, element), CompilerFlags.ERROR);
}
}
private void validateX_InternalDirective(IHeader header, ManifestElement element) {
String internal = element.getDirective(ICoreConstants.INTERNAL_DIRECTIVE);
if (internal == null)
return;
for (int i = 0; i < BOOLEAN_VALUES.length; i++) {
if (BOOLEAN_VALUES[i].equals(internal))
return;
}
String message = NLS.bind(PDECoreMessages.BundleErrorReporter_dir_value,
(new String[] { internal, ICoreConstants.INTERNAL_DIRECTIVE }));
report(message, getPackageLine(header, element), CompilerFlags.ERROR);
}
private void validateX_FriendsDirective(IHeader header, ManifestElement element) {
String friends = element.getDirective(ICoreConstants.FRIENDS_DIRECTIVE);
String internal = element.getDirective(ICoreConstants.INTERNAL_DIRECTIVE);
if (friends != null && internal != null) {
String message = NLS.bind(
PDECoreMessages.BundleErrorReporter_directive_hasNoEffectWith_,
new String[] { ICoreConstants.FRIENDS_DIRECTIVE,
ICoreConstants.INTERNAL_DIRECTIVE });
report(message, getPackageLine(header, element), CompilerFlags.WARNING);
}
}
private void validateAutoStart() {
IHeader header = (IHeader) fHeaders.get(ICoreConstants.ECLIPSE_AUTOSTART);
if (!validateStartHeader(header))
return; // valid start header problems already reported
int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_DEPRECATED);
if (severity != CompilerFlags.IGNORE && TargetPlatform.getTargetVersion() >= 3.2) {
int line = header.getLineNumber();
report(PDECoreMessages.BundleErrorReporter_startHeader_autoStartDeprecated, line + 1, severity, PDEMarkerFactory.M_DEPRECATED_AUTOSTART);
}
}
private void validateLazyStart() {
IHeader header = (IHeader) fHeaders.get(ICoreConstants.ECLIPSE_LAZYSTART);
int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_DEPRECATED);
if (header != null && TargetPlatform.getTargetVersion() < 3.2 && severity != CompilerFlags.IGNORE) {
report(PDECoreMessages.BundleErrorReporter_lazyStart_unsupported,
header.getLineNumber() + 1, severity,
PDEMarkerFactory.NO_RESOLUTION);
} else {
validateStartHeader(header);
}
}
private boolean validateStartHeader(IHeader header) {
if (header == null)
return false;
validateBooleanValue(header);
return exceptionsAttributesValid(header, header.getElements());
}
private boolean exceptionsAttributesValid(IHeader header, ManifestElement[] elements) {
if (elements == null || elements.length == 0)
return true;
int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_ATTRIBUTE);
if (severity == CompilerFlags.IGNORE)
return true;
Enumeration keys = elements[0].getKeys();
if (keys != null && keys.hasMoreElements()) {
String key = (String) keys.nextElement();
if ("exceptions".equals(key)) { //$NON-NLS-1$
String[] values = elements[0].getAttributes(key);
for (int i = 0; i < values.length; i++) {
StringTokenizer st = new StringTokenizer(values[i], ","); //$NON-NLS-1$
while (st.hasMoreTokens()) {
String name = st.nextToken().trim();
if (!getExportedPackages().contains(name)) {
String message = NLS.bind(PDECoreMessages.BundleErrorReporter_NotExistInProject, name);
report(message, getLine(header, name), CompilerFlags.P_UNRESOLVED_IMPORTS);
return false;
}
}
}
}
}
return true;
}
private void validateExtensibleAPI(){
IHeader header = (IHeader) fHeaders.get(ICoreConstants.EXTENSIBLE_API);
if (header != null)
validateBooleanValue(header);
}
public void report(String message, int line, int severity, int problemID, String headerName) {
try {
IMarker marker = report(message, line, severity, problemID);
if (marker != null)
marker.setAttribute(PDEMarkerFactory.MPK_LOCATION_PATH, headerName);
} catch (CoreException e) {
}
}
}