Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
specs-2.8.0, specs-2.9.0
-
None
-
ServiceMix 7.0.1 using org.apache.servicemix.specs.activation-api-1.1-2.8.0
Description
A common way for libraries to register their content handlers is via the CommandMap API (rather than using a mailcap file). For example BouncyCastle's bcmail does this (a lot).
This is generally done in this way:
CommandMap commandMap = CommandMap.getDefaultCommandMap(); if (commandMap instanceof MailcapCommandMap) { ((MailcapCommandMap) commandMap).addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime") }
This is not a problem with the default MailcapCommandMap implementation. But with the overridden MailcapCommandMap, and subclassed OsgiMailcapCommandMap, of this spec this leads to a memory clean of duplicate CommandInfo instances, and for the OSGi case invalid registrations.
Problem 1, invalid registrations:
For OsgiMailcapCommandMap these programmatically added commands will be registered to the last bundle to get its mailcap file registered via the Activator: https://github.com/apache/servicemix-specs/blob/master/activation-api-1.1/src/main/java/org/apache/servicemix/specs/activation/OsgiMailcapCommandMap.java#L45
If the Activator would nullify the "currentBundle" at the end of rebuilding the command map, then entries later registered via the CommandMap via code will not be associated to the last bundle.
This would do the trick
commandMap.addMailcap("", null);
With that in place the call to createDataContentHandler will mostlikely fall through to finding the class via the classloader.
Problem 2, memory leak:
In the above example, calling addMailcap with the same value multiple times will result in multiple registrations.
commandMap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime") commandMap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime") // produces 2 entries
This is sadly a thing bcmail does with signing SMime messages.
With the standard MailcapCommandMap implementation this has no effect as duplicated classnames are filtered out and the CommandInfo instance is created when on request.
The overridden MailcapCommandMap simply appends every CommandInfo to the list without checking for duplicates: https://github.com/apache/servicemix-specs/blob/da08e2fd3ad8bdb026e5e655ae474f35638c52eb/activation-api-1.1/src/main/java/javax/activation/MailcapCommandMap.java#L301