This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat-jakartaee-migration.git
The following commit(s) were added to refs/heads/main by this push:
new 7bdcfbc Correctly handle OSGi headers. PR[#54] by Kyle Smith.
7bdcfbc is described below
commit 7bdcfbc605aa5e912be1c7705c12a4a7392217ab
Author: Mark Thomas <[email protected]>
AuthorDate: Wed Nov 12 16:48:48 2025 +0000
Correctly handle OSGi headers. PR[#54] by Kyle Smith.
---
CHANGES.md | 1 +
pom.xml | 13 ++++
.../apache/tomcat/jakartaee/ManifestConverter.java | 77 ++++++++++++++++++----
.../tomcat/jakartaee/ManifestConverterTest.java | 40 ++++++++++-
src/test/resources/MANIFEST.test.MF | 9 +++
5 files changed, 127 insertions(+), 13 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 625475c..72aeb6b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -3,6 +3,7 @@
## 1.0.10
- When migrating files in place, don't replace the original file if no
conversion has taken place. Based on PR[#78] by Semiao Marco.
- When converting a file in an archive, update the last modified time for that
archive entry. Based on PR[#78] by Semiao Marco.
+- Correctly handle OSGi headers. PR[#54] by Kyle Smith.
- Update ASF parent POM 34. (dependabot/markt)
- Update Commons BCEL to 6.11.0. (dependabot/remm)
- Update Commons Compress to 1.28.0. (dependabot/remm)
diff --git a/pom.xml b/pom.xml
index 1e3ed27..8fa872d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -95,6 +95,11 @@
<version>1.10.15</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.platform</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ <version>3.18.600</version>
+ </dependency>
<!-- Test dependencies -->
<dependency>
@@ -103,6 +108,7 @@
<version>4.13.2</version>
<scope>test</scope>
</dependency>
+
</dependencies>
<profiles>
@@ -282,6 +288,13 @@
<exclude>META-INF/**</exclude>
</excludes>
</filter>
+ <filter>
+ <artifact>org.eclipse.platform:*</artifact>
+ <excludes>
+ <exclude>META-INF/**</exclude>
+ <exclude>module-info.class</exclude>
+ </excludes>
+ </filter>
</filters>
<relocations>
<relocation>
diff --git a/src/main/java/org/apache/tomcat/jakartaee/ManifestConverter.java
b/src/main/java/org/apache/tomcat/jakartaee/ManifestConverter.java
index 63aef73..cc93965 100644
--- a/src/main/java/org/apache/tomcat/jakartaee/ManifestConverter.java
+++ b/src/main/java/org/apache/tomcat/jakartaee/ManifestConverter.java
@@ -33,19 +33,25 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
+import org.eclipse.osgi.util.ManifestElement;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
/**
* Updates Manifests.
*/
public class ManifestConverter implements Converter {
+ private static final String JAKARTA_SERVLET = "jakarta.servlet";
+ private static final Pattern SERVLET_PATTERN =
Pattern.compile("jakarta.servlet([^,]*);version=\"(.*?)\"");
private static final Logger logger =
Logger.getLogger(ManifestConverter.class.getCanonicalName());
private static final StringManager sm =
StringManager.getManager(ManifestConverter.class);
/**
* Manifest converter constructor.
*/
- public ManifestConverter() {}
+ public ManifestConverter() {
+ }
@Override
public boolean accepts(String filename) {
@@ -63,7 +69,8 @@ public class ManifestConverter implements Converter {
Manifest srcManifest = new Manifest(new
ByteArrayInputStream(srcBytes));
Manifest destManifest = new Manifest(srcManifest);
- // Only consider profile conversions, allowing Migration.hasConverted
to be true only when there are actual
+ // Only consider profile conversions, allowing Migration.hasConverted
to be true
+ // only when there are actual
// conversions made
boolean converted = updateValues(destManifest, profile);
removeSignatures(destManifest);
@@ -80,7 +87,6 @@ public class ManifestConverter implements Converter {
return converted;
}
-
private void removeSignatures(Manifest manifest) {
manifest.getMainAttributes().remove(Attributes.Name.SIGNATURE_VERSION);
List<String> signatureEntries = new ArrayList<>();
@@ -98,7 +104,6 @@ public class ManifestConverter implements Converter {
}
}
-
private boolean isCryptoSignatureEntry(Attributes attributes) {
for (Object attributeKey : attributes.keySet()) {
if (attributeKey.toString().endsWith("-Digest")) {
@@ -108,7 +113,6 @@ public class ManifestConverter implements Converter {
return false;
}
-
private boolean updateValues(Manifest manifest, EESpecProfile profile) {
boolean converted = updateValues(manifest.getMainAttributes(),
profile);
for (Attributes attributes : manifest.getEntries().values()) {
@@ -117,7 +121,6 @@ public class ManifestConverter implements Converter {
return converted;
}
-
private boolean updateValues(Attributes attributes, EESpecProfile profile)
{
boolean converted = false;
// Update version info
@@ -128,11 +131,27 @@ public class ManifestConverter implements Converter {
// Purposefully avoid setting result
}
// Update package names in values
- for (Entry<Object,Object> entry : attributes.entrySet()) {
+ for (Entry<Object, Object> entry : attributes.entrySet()) {
String newValue = profile.convert((String) entry.getValue());
- newValue = replaceVersion(newValue);
+ String header = entry.getKey().toString();
+ try {
+ // Need to be careful with OSGI headers.
+ // Specifically, Export-Package cannot specify a version range.
+ // There may be other weird things as well (like directives
that have
+ // jakarta.servlet packages).
+ if (Constants.IMPORT_PACKAGE.equals(header)) {
+ newValue = processImportPackage(newValue);
+ } else if (Constants.EXPORT_PACKAGE.equals(header)) {
+ newValue = processExportPackage(newValue);
+ } else {
+ newValue = replaceVersion(newValue);
+ }
+ } catch (BundleException e) {
+ newValue = replaceVersion(newValue,
!Constants.EXPORT_PACKAGE.equals(header));
+ }
+
// Object comparison is deliberate
- if (newValue != entry.getValue()) {
+ if (!newValue.equals(entry.getValue())) {
entry.setValue(newValue);
converted = true;
}
@@ -140,12 +159,46 @@ public class ManifestConverter implements Converter {
return converted;
}
+ private String processExportPackage(String value) throws BundleException {
+ return processOSGIHeader(value, Constants.EXPORT_PACKAGE, "5.0.0");
+ }
+
+ private String processImportPackage(String value) throws BundleException {
+ return processOSGIHeader(value, Constants.IMPORT_PACKAGE,
"[5.0.0,7.0.0)");
+ }
+
+ private String processOSGIHeader(String value, String header, String
replacement) throws BundleException {
+ List<String> packages = new ArrayList<>();
+ ManifestElement[] elements = ManifestElement.parseHeader(header,
value);
+ for (ManifestElement element : elements) {
+ if (element.getValue().startsWith(JAKARTA_SERVLET)) {
+ String oldVersion =
element.getAttribute(Constants.VERSION_ATTRIBUTE);
+ if (oldVersion != null) {
+ packages.add(element.toString().replace(oldVersion,
replacement));
+ } else {
+ packages.add(element.toString());
+ }
+ } else {
+ packages.add(element.toString());
+ }
+ }
+ if (packages.isEmpty()) {
+ return value;
+ }
+ return String.join(",", packages);
+ }
+
private String replaceVersion(String entryValue) {
- if (entryValue.contains("jakarta.servlet")) {
+ return replaceVersion(entryValue, true);
+ }
+
+ private String replaceVersion(String entryValue, boolean range) {
+ if (entryValue.contains(JAKARTA_SERVLET)) {
StringBuffer builder = new StringBuffer();
- Matcher matcher =
Pattern.compile("jakarta.servlet([^,]*);version=\"(.*?)\"").matcher(entryValue);
+ Matcher matcher = SERVLET_PATTERN.matcher(entryValue);
while (matcher.find()) {
- matcher.appendReplacement(builder,
"jakarta.servlet$1;version=\"[5.0.0,7.0.0)\"");
+ String version = range ? "[5.0.0,7.0.0)" : "5.0.0";
+ matcher.appendReplacement(builder,
"jakarta.servlet$1;version=\"" + version + "\"");
}
matcher.appendTail(builder);
return builder.toString();
diff --git
a/src/test/java/org/apache/tomcat/jakartaee/ManifestConverterTest.java
b/src/test/java/org/apache/tomcat/jakartaee/ManifestConverterTest.java
index 6748dba..1775537 100644
--- a/src/test/java/org/apache/tomcat/jakartaee/ManifestConverterTest.java
+++ b/src/test/java/org/apache/tomcat/jakartaee/ManifestConverterTest.java
@@ -14,12 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.tomcat.jakartaee;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import org.junit.Test;
public class ManifestConverterTest {
@@ -34,4 +35,41 @@ public class ManifestConverterTest {
assertFalse(converter.accepts("xMETA-INF/MANIFEST.MF"));
assertFalse(converter.accepts("WEB-INF/bundles/com.example.bundle/xMETA-INF/MANIFEST.MF"));
}
+
+
+ @Test
+ public void testConvert() throws IOException {
+ ManifestConverter converter = new ManifestConverter();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ boolean converted = converter.convert("/MANIFEST.test.MF",
getClass().getResourceAsStream("/MANIFEST.test.MF"),
+ os, EESpecProfiles.TOMCAT);
+ assertTrue(converted);
+
+ String result = os.toString("UTF-8");
+ System.out.println(result);
+ assertTrue(result.length() != 0);
+ result = result.replaceAll("\\s", "");
+
+ // Basic test
+ String imports = "jakarta.servlet;version=\"[5.0.0,7.0.0)\"";
+
+ // Test with directives
+ String imports2 =
"jakarta.servlet.http;version=\"[5.0.0,7.0.0)\";resolution:=\"optional\"";
+ assertTrue(result.contains(imports));
+ assertTrue(result.contains(imports2));
+
+ // Test with directive and version
+ String exports =
"jakarta.servlet;version=\"5.0.0\";uses:=\"org.eclipse.core.runtime\"";
+
+ // Same as above, with javax.servlet package in the directive
+ String exports2 =
"jakarta.servlet.http;version=\"5.0.0\";uses:=\"jakarta.servlet\"";
+
+ // Export a different package that has javax.servlet in a directive so
version
+ // isn't updated
+ String exports3 =
"org.apache.tomcat.jakartaee.test;version=\"1.0.0\";uses:=\"jakarta.servlet\"";
+
+ assertTrue(result.contains(exports));
+ assertTrue(result.contains(exports2));
+ assertTrue(result.contains(exports3));
+ }
}
diff --git a/src/test/resources/MANIFEST.test.MF
b/src/test/resources/MANIFEST.test.MF
new file mode 100644
index 0000000..06cbcfb
--- /dev/null
+++ b/src/test/resources/MANIFEST.test.MF
@@ -0,0 +1,9 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Version: 1.0.0.qualifier
+Bundle-SymbolicName: org.apache.tomcat.jakartaee.test
+Import-Package: javax.servlet;version="[2.0.0,5.0.0)",
+ javax.servlet.http;resolution:=optional;version="[2.0.0,5.0.0)"
+Export-Package: javax.servlet;uses:="org.eclipse.core.runtime";version="4.0.0",
+ javax.servlet.http;uses:="javax.servlet";version="4.0.0",
+ org.apache.tomcat.jakartaee.test;uses:="javax.servlet";version="1.0.0"
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]