Reorganized/improved R3 manifest header conversion to R4 metadata. Fixed
a bug that was allowing duplicate import declarations when an R3 bundle
had both an import and export header for a given package.
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@418715 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
index 8dfd354..437ce38 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -2953,55 +2953,8 @@
// Create map to check for duplicate imports/exports.
Map dupeMap = new HashMap();
- // Get import packages from bundle manifest.
- R4Package[] pkgs = R4Package.parseImportOrExportHeader(
- (String) headerMap.get(Constants.IMPORT_PACKAGE));
-
- // Create non-duplicated import array.
- dupeMap.clear();
- for (int i = 0; i < pkgs.length; i++)
- {
- if (dupeMap.get(pkgs[i].getName()) == null)
- {
- dupeMap.put(pkgs[i].getName(), new R4Import(pkgs[i]));
- }
- else
- {
- // TODO: FRAMEWORK - Determine if we should error here.
- m_logger.log(Logger.LOG_WARNING,
- "Duplicate import - " + pkgs[i].getName());
- }
- }
- R4Import[] imports =
- (R4Import[]) dupeMap.values().toArray(new R4Import[dupeMap.size()]);
-
- // Check to make sure that R3 bundles have only specified
- // the 'specification-version' attribute and no directives.
- if (version.equals("1"))
- {
- for (int i = 0; (imports != null) && (i < imports.length); i++)
- {
- if (imports[i].getDirectives().length != 0)
- {
- throw new BundleException("R3 imports cannot contain directives.");
- }
- // NOTE: This is checking for "version" rather than "specification-version"
- // because the package class normalizes to "version" to avoid having
- // future special cases. This could be changed if more strict behavior
- // is required.
- if ((imports[i].getVersionHigh() != null) ||
- (imports[i].getAttributes().length > 1) ||
- ((imports[i].getAttributes().length == 1) &&
- (!imports[i].getAttributes()[0].getName().equals(FelixConstants.VERSION_ATTRIBUTE))))
- {
- throw new BundleException(
- "Import does not conform to R3 syntax: " + imports[i]);
- }
- }
- }
-
// Get export packages from bundle manifest.
- pkgs = R4Package.parseImportOrExportHeader(
+ R4Package[] pkgs = R4Package.parseImportOrExportHeader(
(String) headerMap.get(Constants.EXPORT_PACKAGE));
// Create non-duplicated export array.
@@ -3022,65 +2975,27 @@
R4Export[] exports =
(R4Export[]) dupeMap.values().toArray(new R4Export[dupeMap.size()]);
+ // Get import packages from bundle manifest.
+ pkgs = R4Package.parseImportOrExportHeader(
+ (String) headerMap.get(Constants.IMPORT_PACKAGE));
- // Check to make sure that R3 bundles have only specified
- // the 'specification-version' attribute and no directives.
- // In addition, all R3 exports imply imports, so add a
- // corresponding import for each export.
- if (version.equals("1"))
+ // Create non-duplicated import array.
+ dupeMap.clear();
+ for (int i = 0; i < pkgs.length; i++)
{
- for (int i = 0; (exports != null) && (i < exports.length); i++)
+ if (dupeMap.get(pkgs[i].getName()) == null)
{
- if (exports[i].getDirectives().length != 0)
- {
- throw new BundleException("R3 exports cannot contain directives.");
- }
- // NOTE: This is checking for "version" rather than "specification-version"
- // because the package class normalizes to "version" to avoid having
- // future special cases. This could be changed if more strict behavior
- // is required.
- if ((exports[i].getAttributes().length > 1) ||
- ((exports[i].getAttributes().length == 1) &&
- (!exports[i].getAttributes()[0].getName().equals(FelixConstants.VERSION_ATTRIBUTE))))
- {
- throw new BundleException(
- "Export does not conform to R3 syntax: " + imports[i]);
- }
+ dupeMap.put(pkgs[i].getName(), new R4Import(pkgs[i]));
}
-
- R4Import[] newImports = new R4Import[imports.length + exports.length];
- System.arraycopy(imports, 0, newImports, 0, imports.length);
- for (int i = 0; i < exports.length; i++)
+ else
{
- newImports[i + imports.length] = new R4Import(exports[i]);
- }
- imports = newImports;
- }
-
- // For R3 bundles, add a "uses" directive onto each export
- // that references every other import (which will include
- // exports, since export implies import); this is
- // necessary since R3 bundles assumed a single class space,
- // but R4 allows for multiple class spaces.
- if (version.equals("1"))
- {
- String usesValue = "";
- for (int i = 0; (imports != null) && (i < imports.length); i++)
- {
- usesValue = usesValue
- + ((usesValue.length() > 0) ? "," : "")
- + imports[i].getName();
- }
- R4Directive uses = new R4Directive(
- FelixConstants.USES_DIRECTIVE, usesValue);
- for (int i = 0; (exports != null) && (i < exports.length); i++)
- {
- exports[i] = new R4Export(
- exports[i].getName(),
- new R4Directive[] { uses },
- exports[i].getAttributes());
+ // TODO: FRAMEWORK - Determine if we should error here.
+ m_logger.log(Logger.LOG_WARNING,
+ "Duplicate import - " + pkgs[i].getName());
}
}
+ R4Import[] imports =
+ (R4Import[]) dupeMap.values().toArray(new R4Import[dupeMap.size()]);
// Get dynamic import packages from bundle manifest.
pkgs = R4Package.parseImportOrExportHeader(
@@ -3104,19 +3019,109 @@
R4Import[] dynamics =
(R4Import[]) dupeMap.values().toArray(new R4Import[dupeMap.size()]);
- // Check to make sure that R3 bundles have no attributes or
- // directives.
+ // Do validity checking and conversion on bundles with R3 headers.
if (version.equals("1"))
{
- for (int i = 0; (dynamics != null) && (i < dynamics.length); i++)
+ // Check to make sure that R3 bundles have only specified
+ // the 'specification-version' attribute and no directives
+ // on their exports.
+ for (int i = 0; (exports != null) && (i < exports.length); i++)
{
- if (dynamics[i].getDirectives().length != 0)
+ if (exports[i].getDirectives().length != 0)
{
- throw new BundleException("R3 dynamic imports cannot contain directives.");
+ throw new BundleException("R3 exports cannot contain directives.");
}
- if (dynamics[i].getAttributes().length != 0)
+ // NOTE: This is checking for "version" rather than "specification-version"
+ // because the package class normalizes to "version" to avoid having
+ // future special cases. This could be changed if more strict behavior
+ // is required.
+ if ((exports[i].getAttributes().length > 1) ||
+ ((exports[i].getAttributes().length == 1) &&
+ (!exports[i].getAttributes()[0].getName().equals(FelixConstants.VERSION_ATTRIBUTE))))
{
- throw new BundleException("R3 dynamic imports cannot contain attributes.");
+ throw new BundleException(
+ "Export does not conform to R3 syntax: " + imports[i]);
+ }
+ }
+
+ // Check to make sure that R3 bundles have only specified
+ // the 'specification-version' attribute and no directives
+ // on their imports.
+ for (int i = 0; (imports != null) && (i < imports.length); i++)
+ {
+ if (imports[i].getDirectives().length != 0)
+ {
+ throw new BundleException("R3 imports cannot contain directives.");
+ }
+ // NOTE: This is checking for "version" rather than "specification-version"
+ // because the package class normalizes to "version" to avoid having
+ // future special cases. This could be changed if more strict behavior
+ // is required.
+ if ((imports[i].getVersionHigh() != null) ||
+ (imports[i].getAttributes().length > 1) ||
+ ((imports[i].getAttributes().length == 1) &&
+ (!imports[i].getAttributes()[0].getName().equals(FelixConstants.VERSION_ATTRIBUTE))))
+ {
+ throw new BundleException(
+ "Import does not conform to R3 syntax: " + imports[i]);
+ }
+ }
+
+ // Since all R3 exports imply an import, add a corresponding
+ // import for each existing export. Create non-duplicated import array.
+ dupeMap.clear();
+ // Add existing imports.
+ for (int i = 0; i < imports.length; i++)
+ {
+ dupeMap.put(imports[i].getName(), imports[i]);
+ }
+ // Add import for each export.
+ for (int i = 0; i < exports.length; i++)
+ {
+ if (dupeMap.get(exports[i].getName()) == null)
+ {
+ dupeMap.put(exports[i].getName(), new R4Import(exports[i]));
+ }
+ }
+ imports =
+ (R4Import[]) dupeMap.values().toArray(new R4Import[dupeMap.size()]);
+
+ // Add a "uses" directive onto each export of R3 bundles
+ // that references every other import (which will include
+ // exports, since export implies import); this is
+ // necessary since R3 bundles assumed a single class space,
+ // but R4 allows for multiple class spaces.
+ String usesValue = "";
+ for (int i = 0; (imports != null) && (i < imports.length); i++)
+ {
+ usesValue = usesValue
+ + ((usesValue.length() > 0) ? "," : "")
+ + imports[i].getName();
+ }
+ R4Directive uses = new R4Directive(
+ FelixConstants.USES_DIRECTIVE, usesValue);
+ for (int i = 0; (exports != null) && (i < exports.length); i++)
+ {
+ exports[i] = new R4Export(
+ exports[i].getName(),
+ new R4Directive[] { uses },
+ exports[i].getAttributes());
+ }
+
+ // Check to make sure that R3 bundles have no attributes or
+ // directives on their dynamic imports.
+ if (version.equals("1"))
+ {
+ for (int i = 0; (dynamics != null) && (i < dynamics.length); i++)
+ {
+ if (dynamics[i].getDirectives().length != 0)
+ {
+ throw new BundleException("R3 dynamic imports cannot contain directives.");
+ }
+ if (dynamics[i].getAttributes().length != 0)
+ {
+ throw new BundleException("R3 dynamic imports cannot contain attributes.");
+ }
}
}
}