You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ga...@apache.org on 2012/10/11 17:47:44 UTC
svn commit: r1397121 -
/geronimo/server/branches/3.0/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ResolverErrorAnalyzer.java
Author: gawor
Date: Thu Oct 11 15:47:43 2012
New Revision: 1397121
URL: http://svn.apache.org/viewvc?rev=1397121&view=rev
Log:
GERONIMO-6397: Provide details on import package unsatisfied error messages for OSGi applications
Modified:
geronimo/server/branches/3.0/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ResolverErrorAnalyzer.java
Modified: geronimo/server/branches/3.0/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ResolverErrorAnalyzer.java
URL: http://svn.apache.org/viewvc/geronimo/server/branches/3.0/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ResolverErrorAnalyzer.java?rev=1397121&r1=1397120&r2=1397121&view=diff
==============================================================================
--- geronimo/server/branches/3.0/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ResolverErrorAnalyzer.java (original)
+++ geronimo/server/branches/3.0/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ResolverErrorAnalyzer.java Thu Oct 11 15:47:43 2012
@@ -29,6 +29,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import org.eclipse.osgi.service.resolver.BaseDescription;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.BundleSpecification;
import org.eclipse.osgi.service.resolver.ExportPackageDescription;
@@ -43,6 +44,7 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
/*
* Collects resolver errors for a given set of bundles and trims out any errors caused by
@@ -66,31 +68,21 @@ public class ResolverErrorAnalyzer {
}
public String getErrorsAsString(Collection<Bundle> bundles) {
- Collection<String> errors = getErrors(bundles);
+ Collection<ErrorDetail> errors = getErrors(bundles);
if (errors.isEmpty()) {
return null;
} else {
- String LF = System.getProperty("line.separator");
- StringBuilder builder = new StringBuilder();
- builder.append("The following problems were detected:").append(LF);
- Iterator<String> iterator = errors.iterator();
- while (iterator.hasNext()) {
- builder.append(" ");
- builder.append(iterator.next());
- if (iterator.hasNext()) {
- builder.append(LF);
- }
- }
- return builder.toString();
+ ErrorDetail error = new ErrorDetail("The following problems were detected:", errors);
+ return error.toString();
}
}
- public Collection<String> getErrors(Collection<Bundle> bundles) {
+ public Collection<ErrorDetail> getErrors(Collection<Bundle> bundles) {
if (!hasPlatformAdmin()) {
return Collections.emptyList();
}
- List<String> errors = new ArrayList<String>();
+ List<ErrorDetail> errors = new ArrayList<ErrorDetail>();
ServiceReference ref = bundleContext.getServiceReference(PlatformAdmin.class.getName());
try {
@@ -113,7 +105,7 @@ public class ResolverErrorAnalyzer {
return errors;
}
- private void collectErrors(BundleDescription bundle, State state, List<BundleDescription> bundleDescriptions, Collection<String> errorList) {
+ private void collectErrors(BundleDescription bundle, State state, List<BundleDescription> bundleDescriptions, Collection<ErrorDetail> errorList) {
ResolverError[] errors = state.getResolverErrors(bundle);
for (ResolverError error : errors) {
VersionConstraint constraint = error.getUnsatisfiedConstraint();
@@ -126,7 +118,9 @@ public class ResolverErrorAnalyzer {
continue;
}
if (isSatisfied(importPackageSpecification, bundleDescriptions) == null) {
- errorList.add("The package dependency " + versionToString(importPackageSpecification) + " required by bundle " + bundleToString(bundle) + " cannot be satisfied.");
+ ErrorDetail errorDetail = new ErrorDetail("The package dependency " + versionToString(importPackageSpecification) + " required by bundle " + bundleToString(bundle) + " cannot be satisfied.");
+ getUnsatisfiedReason(state, importPackageSpecification, errorDetail);
+ errorList.add(errorDetail);
}
break;
case MISSING_REQUIRE_BUNDLE:
@@ -136,25 +130,25 @@ public class ResolverErrorAnalyzer {
continue;
}
if (isSatisfied(bundleSpecification, bundleDescriptions) == null) {
- errorList.add("The bundle dependency " + versionToString(bundleSpecification) + " required by bundle " + bundleToString(bundle) + " cannot be satisfied.");
+ errorList.add(new ErrorDetail("The bundle dependency " + versionToString(bundleSpecification) + " required by bundle " + bundleToString(bundle) + " cannot be satisfied."));
}
break;
case MISSING_FRAGMENT_HOST:
HostSpecification hostSpecification = (HostSpecification) constraint;
if (isSatisfied(hostSpecification, bundleDescriptions) == null) {
- errorList.add("The host bundle dependency " + versionToString(hostSpecification) + " required by bundle " + bundleToString(bundle) + " cannot be satisfied.");
+ errorList.add(new ErrorDetail("The host bundle dependency " + versionToString(hostSpecification) + " required by bundle " + bundleToString(bundle) + " cannot be satisfied."));
}
break;
case IMPORT_PACKAGE_USES_CONFLICT:
ImportPackageSpecification usesImportPackageSpecification = (ImportPackageSpecification) constraint;
- errorList.add("The package dependency " + versionToString(usesImportPackageSpecification) + " required by bundle " + bundleToString(bundle) + " cannot be resolved due to uses directive conflict.");
+ errorList.add(new ErrorDetail("The package dependency " + versionToString(usesImportPackageSpecification) + " required by bundle " + bundleToString(bundle) + " cannot be resolved due to uses directive conflict."));
break;
case REQUIRE_BUNDLE_USES_CONFLICT:
BundleSpecification usesBundleSpecification = (BundleSpecification) constraint;
- errorList.add("The bundle dependency " + versionToString(usesBundleSpecification) + " required by bundle " + bundleToString(bundle) + " cannot be resolved due to uses directive conflict.");
+ errorList.add(new ErrorDetail("The bundle dependency " + versionToString(usesBundleSpecification) + " required by bundle " + bundleToString(bundle) + " cannot be resolved due to uses directive conflict."));
break;
default:
- errorList.add(error.toString());
+ errorList.add(new ErrorDetail(error.toString()));
break;
}
}
@@ -183,6 +177,59 @@ public class ResolverErrorAnalyzer {
return null;
}
+ private void getUnsatisfiedReason(State state, ImportPackageSpecification importPackage, ErrorDetail errorDetail) {
+ String packageName = importPackage.getName();
+ BundleDescription[] bundles = state.getBundles();
+ List<ExportPackageDescription> packageExportList = new ArrayList<ExportPackageDescription>();
+ for (BundleDescription bundle : bundles) {
+ findExportPackage(packageName, bundle.getExportPackages(), packageExportList);
+ }
+
+ int size = packageExportList.size();
+ if (size == 0) {
+ errorDetail.add("Package " + packageName + " is not exported by any bundle.");
+ } else if (size == 1) {
+ ExportPackageDescription packageExport = packageExportList.get(0);
+ BundleDescription exporter = packageExport.getExporter();
+ errorDetail.add("Bundle " + bundleToString(exporter) + " exports " + exportToString(packageExport) + " package which does not satisfy the dependency.");
+ } else {
+ for (ExportPackageDescription packageExport : packageExportList) {
+ BundleDescription exporter = packageExport.getExporter();
+ if (exporter.isResolved() &&
+ !isSelectedExportPackage(packageExport) &&
+ importPackage.isSatisfiedBy(packageExport)) {
+ // export is not selected but it does satisfy the import
+ errorDetail.add("Bundle " + bundleToString(exporter) + " exports " + exportToString(packageExport) + " package which satisfies the dependency but is unselected.");
+ } else {
+ errorDetail.add("Bundle " + bundleToString(exporter) + " exports " + exportToString(packageExport) + " package which does not satisfy the dependency.");
+ }
+ }
+ }
+ }
+
+ private void findExportPackage(String packageName, ExportPackageDescription[] exportedPackages, List<ExportPackageDescription> list) {
+ if (exportedPackages != null) {
+ for (ExportPackageDescription exportedPackage : exportedPackages) {
+ if (packageName.equals(exportedPackage.getName())) {
+ list.add(exportedPackage);
+ }
+ }
+ }
+ }
+
+ private boolean isSelectedExportPackage(ExportPackageDescription exportedPackage) {
+ BundleDescription exporter = exportedPackage.getExporter();
+ ExportPackageDescription[] selectedExportPackages = exporter.getSelectedExports();
+ if (selectedExportPackages != null) {
+ for (ExportPackageDescription selectedExportedPackage : selectedExportPackages) {
+ if (exportedPackage.equals(selectedExportedPackage)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private static String bundleToString(BundleDescription bundle) {
return bundle.getSymbolicName() + " [" + bundle.getBundleId() + "]";
}
@@ -201,4 +248,64 @@ public class ResolverErrorAnalyzer {
return constraint.getName() + "; " + versionAttribute;
}
}
+
+ private static String exportToString(ExportPackageDescription exportPackage) {
+ Version version = exportPackage.getVersion();
+ if (version == null) {
+ return exportPackage.getName();
+ } else {
+ String versionAttribute = "version=\"" + version + "\"";
+ return exportPackage.getName() + "; " + versionAttribute;
+ }
+ }
+
+ public static class ErrorDetail {
+
+ public static final String LF = System.getProperty("line.separator");
+
+ private String message;
+ private Collection<ErrorDetail> details;
+
+ public ErrorDetail(String message) {
+ this.message = message;
+ }
+
+ public ErrorDetail(String message, Collection<ErrorDetail> details) {
+ this.message = message;
+ this.details = details;
+ }
+
+ public void add(ErrorDetail detail) {
+ if (details == null) {
+ details = new ArrayList<ErrorDetail>();
+ }
+ details.add(detail);
+ }
+
+ public void add(String message) {
+ add(new ErrorDetail(message));
+ }
+
+ public void toString(StringBuilder builder, String pad) {
+ builder.append(message);
+ if (details != null && !details.isEmpty()) {
+ builder.append(LF);
+ Iterator<ErrorDetail> iterator = details.iterator();
+ while (iterator.hasNext()) {
+ builder.append(pad);
+ iterator.next().toString(builder, pad + pad);
+ if (iterator.hasNext()) {
+ builder.append(LF);
+ }
+ }
+ }
+ }
+
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ toString(builder, " ");
+ return builder.toString();
+ }
+
+ }
}