* package accordingly.
*/
public void execute() throws BuildException {
if (0==exportsResourceCollections.size()
&& 0==implsResourceCollections.size()) {
throw new BuildException("Neither exports nor impls specified",
getLocation());
}
// First analyze the exports resource collections
for (Iterator it = exportsResourceCollections.iterator(); it.hasNext(); ) {
final ResourceCollection rc = (ResourceCollection) it.next();
for (Iterator rcIt = rc.iterator(); rcIt.hasNext();) {
final Resource res = (Resource) rcIt.next();
log("Exports resource: "+res, Project.MSG_DEBUG);
analyze(res);
}
}// Scan done
// Get the sub-set of the provided packages that are the exports set
final Set providedExportSet = new TreeSet(bpInfo.getProvidedPackages());
final Set manifestExportSet = getPredefinedExportSet();
if (null!=manifestExportSet) {
// An Export-Package header was given it shall contain
// precisely the provided export set of Java packages.
if (!manifestExportSet.equals(providedExportSet)) {
// Found export package missmatch
log("Provided package to export: " +providedExportSet,
Project.MSG_ERR);
log("Given Export-Package header: " +manifestExportSet,
Project.MSG_ERR);
final StringBuffer msg = new StringBuffer();
final TreeSet tmp = new TreeSet(manifestExportSet);
tmp.removeAll(providedExportSet);
if (0<tmp.size()) {
msg.append("The following non-provided packages are present in the ")
.append("Export-Package header: ")
.append(tmp.toString())
.append(". ");
}
tmp.clear();
tmp.addAll(providedExportSet);
tmp.removeAll(manifestExportSet);
if (0<tmp.size()) {
if (0<msg.length()) {
msg.append("\n");
}
msg.append("The following packages are missing from ")
.append("the given Export-Package header: ")
.append(tmp.toString())
.append(".");
}
tmp.clear();
if (failOnExports) {
log(msg.toString(), Project.MSG_ERR);
throw new BuildException(msg.toString(), getLocation());
} else {
log(msg.toString(), Project.MSG_WARN);
}
}
}
log("Provided packages to export: " +providedExportSet,
Project.MSG_VERBOSE);
// Analyze the impls resource collections to find all provided
// Java packages.
for (Iterator it = implsResourceCollections.iterator(); it.hasNext(); ) {
final ResourceCollection rc = (ResourceCollection) it.next();
for (Iterator rcIt = rc.iterator(); rcIt.hasNext();) {
final Resource res = (Resource) rcIt.next();
log("Impl resource: "+res, Project.MSG_DEBUG);
analyze(res);
}
}// Scan done
// Get the set of packages provided by the bundle
bpInfo.toJavaNames(); // Make package name in bpInfo '.' separated.
log("All provided packages: "
+bpInfo.getProvidedPackagesAsExportPackageValue(),
Project.MSG_VERBOSE);
// created importSet from the set of unprovided referenced packages
final SortedSet unprovidedReferencedPackages
= bpInfo.getUnprovidedReferencedPackages();
log("Un-provided referenced packages: " +unprovidedReferencedPackages,
Project.MSG_DEBUG);
// The set of referenced packages that matches one of the
// stdImport patterns.
final SortedSet ignoredReferencedPackages = new TreeSet();
// Remove all packages with names like "java.*" (full set of
// patterns are given by the stdImports set). Such packages must
// not be present in the importSet.
for (Iterator urpIt = unprovidedReferencedPackages.iterator();
urpIt.hasNext(); ) {
final String pkgName = (String) urpIt.next();
if (isStdImport(pkgName)) {
urpIt.remove();
ignoredReferencedPackages.add(pkgName);
}
}
log("Referenced packages to import: " +unprovidedReferencedPackages,
Project.MSG_DEBUG);
importSet.addAll(unprovidedReferencedPackages);
final SortedSet unprovidedExtraImportSet = new TreeSet(extraImportSet);
unprovidedExtraImportSet.removeAll(bpInfo.getProvidedPackages());
log("Un-provided extra packages to import: " +unprovidedExtraImportSet,
Project.MSG_DEBUG);
importSet.addAll(unprovidedExtraImportSet);
// The set of packages that will be mentioned in the
// Export-Package or the Import-Package header.
final Set allImpExpPkgs = new TreeSet(providedExportSet);
allImpExpPkgs.addAll(importSet);
bpInfo.postProcessUsingMap(ignoredReferencedPackages, allImpExpPkgs);
//log(bpInfo.toString(), Project.MSG_INFO);
// Data collection done - write back properties
final Project proj = getProject();
if(!"".equals(exportsProperty)) {
// A property name for the Export-Package header value has been specified
final String exportsVal = proj.getProperty(exportsProperty);
if (BundleManifestTask.isPropertyValueEmpty(exportsVal)) {
// No value given, shall it be derived?
if (!bImportsOnly) {
if (0==providedExportSet.size()) {
proj.setProperty(exportsProperty,
BundleManifestTask.BUNDLE_EMPTY_STRING);
log("No packages exported, leaving '" +exportsProperty +"' empty.",
Project.MSG_VERBOSE);
} else {
final String newExportsVal
= buildExportPackagesValue(providedExportSet);
log("Setting '" +exportsProperty +"' to '"+newExportsVal +"'",
Project.MSG_VERBOSE);
proj.setProperty(exportsProperty, newExportsVal);
}
}
} else {
// Export-Package given; add version and uses directives.
final String newExportsVal = validateExportPackagesValue(exportsVal);
if (!exportsVal.equals(newExportsVal)) {
log("Updating \"" +exportsProperty +"\" to \""+newExportsVal +"\"",
Project.MSG_VERBOSE);
proj.setProperty(exportsProperty, newExportsVal);
}
}
}
if(!"".equals(importsProperty)) {
String importsVal = proj.getProperty(importsProperty);
if (BundleManifestTask.isPropertyValueEmpty(importsVal)) {
// No Import-Package given; use derived value.
if (0==importSet.size()) {
log("No packages to import, leaving \"" +importsProperty +"\" empty.",
Project.MSG_VERBOSE);
proj.setProperty(importsProperty,
BundleManifestTask.BUNDLE_EMPTY_STRING);
} else {
importsVal = toString(importSet, ",");
log("Setting \"" +importsProperty +"\" to \""+importsVal +"\"",
Project.MSG_VERBOSE);
proj.setProperty(importsProperty, importsVal);
}
} else {
// Import-Package given; check that all derived packages are
// present and that there are no duplicated packages.
final TreeSet givenImportSet = new TreeSet();
final Iterator impIt = Util.parseEntries("import.package",importsVal,
true, true, false );
while (impIt.hasNext()) {
final Map impEntry = (Map) impIt.next();
final String pkgName = (String) impEntry.get("$key");
if (!givenImportSet.add( pkgName )) {
final String msg = "The package '" +pkgName
+"' is mentioned twice in the given 'Import-Package' manifest "
+"header: '" +importsVal +"'.";
log(msg, Project.MSG_ERR);
throw new BuildException(msg, getLocation());
}
}
givenImportSet.removeAll(bpInfo.getProvidedPackages());
final TreeSet missingImports = new TreeSet(importSet);
missingImports.removeAll(givenImportSet);
if (0<missingImports.size()) {
log("External packages: "+importSet, Project.MSG_ERR);
log("Imported packages: "+givenImportSet, Project.MSG_ERR);
log("Provided packages: "+bpInfo.getProvidedPackages(),
Project.MSG_ERR);
final String msg = "The following external packages are used by "
+"the bundle but not mentioned in the Import-Package manifest "
+"header: " +missingImports;
log(msg, Project.MSG_ERR );
if (failOnImports) {
throw new BuildException(msg, getLocation());
}
}
final TreeSet extraImports = new TreeSet(givenImportSet);
extraImports.removeAll(importSet);
if (0<extraImports.size()) {
log("External packages: "+importSet, Project.MSG_ERR);
log("Imported packages: "+givenImportSet, Project.MSG_ERR);
log("The following packages are mentioned in the Import-Package"
+" manifest header but not used by the included classes: "
+extraImports, Project.MSG_WARN );
}
}
}
// Try to be a bit clever when writing back bundle activator
if(!"".equals(activatorProperty) && bSetActivator) {
final String activatorVal = proj.getProperty(activatorProperty);
if (BundleManifestTask.isPropertyValueEmpty(activatorVal)) {
// No Bundle-Activator given; use derived value if possible.
switch(bpInfo.countProvidedActivatorClasses()) {
case 0:
if (!bActivatorOptional) {
final String msg1 = "Requested to derive Bundle-Activator but "
+"there is no class implementing BundleActivator.";
log(msg1, Project.MSG_ERR);
if (failOnActivator) {
throw new BuildException(msg1, getLocation());
}
}
break;
case 1:
String clazz = bpInfo.getActivatorClass();
proj.setProperty(activatorProperty, clazz);
break;
default:
final String msg2 = "Manual selection of Bundle-Activator "
+"is needed since the set of included classes contains "
+"more than one candidate: "
+bpInfo.providedActivatorClassesAsString();
log(msg2, Project.MSG_ERR);
if (failOnActivator) {
throw new BuildException(msg2, getLocation());
}
}
} else {
// Bundle-Activator given; check that it is correct.
if (0==bpInfo.countProvidedActivatorClasses()) {
log("No class implementing BundleActivator found", Project.MSG_ERR);
} else {
final String givenClazz = proj.getProperty(activatorProperty).trim();
if (!bpInfo.providesActivatorClass(givenClazz)) {
final String msg = "The specified BundleActivator '" +givenClazz
+"' is not a member of the set of included classes that"
+" implements BundleActivator: "
+bpInfo.providedActivatorClassesAsString();
log(msg, Project.MSG_WARN);
if (failOnActivator) {
throw new BuildException(msg, getLocation());
}
}
}
}
}