jakartaee / jaf-api

Jakarta Activation Specification project
https://jakartaee.github.io/jaf-api/
BSD 3-Clause "New" or "Revised" License
32 stars 33 forks source link

JDK8: java.lang.ClassCastException: com.sun.activation.registries.MailcapFile cannot be cast to jakarta.activation.MailcapRegistry #103

Closed jbescos closed 1 year ago

jbescos commented 1 year ago

Describe the bug It was reported in mail: https://github.com/eclipse-ee4j/angus-mail/issues/37

Issue is explained here: https://github.com/eclipse-ee4j/angus-mail/issues/37#issuecomment-1293303298

To Reproduce Reproducer here with JDK8: https://github.com/eclipse-ee4j/angus-mail/issues/37#issue-1419900440

Expected behavior No error should be thrown.

Additional context To see the ClassCastException you just need to iterate over the list, for example:

    for (MailcapRegistry registry : dbv) {
        System.out.println("Value: " + registry);
        if (registry != null) {
            System.out.println("Class: " + registry.getClass());
        }
    }
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.568 s <<< FAILURE! - in com.icegreen.greenmail.imap.commands.ImapProtocolTest
[ERROR] com.icegreen.greenmail.imap.commands.ImapProtocolTest.testUidSearchTextWithCharset  Time elapsed: 0.492 s  <<< ERROR!
java.lang.ClassCastException: com.sun.activation.registries.MailcapFile cannot be cast to jakarta.activation.MailcapRegistry
    at jakarta.activation.MailcapCommandMap.<init>(MailcapCommandMap.java:179)
    at jakarta.activation.CommandMap.getDefaultCommandMap(CommandMap.java:60)
    at jakarta.activation.DataHandler.getCommandMap(DataHandler.java:128)
    at jakarta.activation.DataHandler.getDataContentHandler(DataHandler.java:590)
    at jakarta.activation.DataHandler.writeTo(DataHandler.java:290)
    at jakarta.mail.internet.MimeUtility.getEncoding(MimeUtility.java:316)
    at jakarta.mail.internet.MimeBodyPart.updateHeaders(MimeBodyPart.java:1580)
    at jakarta.mail.internet.MimeMessage.updateHeaders(MimeMessage.java:2265)
    at jakarta.mail.internet.MimeMessage.saveChanges(MimeMessage.java:2225)
    at jakarta.mail.Transport.send(Transport.java:99)
    at com.icegreen.greenmail.util.GreenMailUtil.sendMimeMessage(GreenMailUtil.java:266)
    at com.icegreen.greenmail.util.GreenMailUtil.sendTextEmail(GreenMailUtil.java:256)
    at com.icegreen.greenmail.imap.commands.ImapProtocolTest.beforeEachTest(ImapProtocolTest.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at com.icegreen.greenmail.junit.GreenMailRule$1.evaluate(GreenMailRule.java:63)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:377)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:284)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:248)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:167)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:456)
    at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:169)
    at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:595)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:581)

Otherwise the issue is hidden by this other exception:

java.lang.ArrayStoreException
    at java.lang.System.arraycopy(Native Method)
    at java.util.ArrayList.toArray(ArrayList.java:414)
    at jakarta.activation.MailcapCommandMap.<init>(MailcapCommandMap.java:181)
        ...
jmehrens commented 1 year ago

I was tempted to file an RFE on that unhelpful java.lang.ArrayStoreException. However, JDK11 has JDK-8204943: Improve message of ArrayStoreException so it would provide the details needed to get at the core issue. Since activation is removed in JDK9+ it might just be a JDK8 error.

jbescos commented 1 year ago

This is really odd.

The next will add in the list (this is how it is done currently):

MailcapRegistry registry = getImplementation().getByInputStream(clis);
if (registry != null) {
    v.add(registry);
}

The next will NOT add in the list:

MailcapRegistry registry = getImplementation().getByInputStream(clis);
if (registry != null && registry instanceof MailcapRegistry) {
    v.add(registry);
}

If this is evaluated as false: registry instanceof MailcapRegistry , then this line should throw a ClassCastException: MailcapRegistry registry = getImplementation().getByInputStream(clis);. But it is not throwing an exception there. It is thrown later when the list is iterated.

I have run the example with a javaagent that writes the bytecode of the classes in runtime and it shows that the class MailcapFile is the one that belongs to JDK8. This is consistent with the error.

jbescos commented 1 year ago

Solving it in https://github.com/eclipse-ee4j/angus-activation/pull/11

lukasj commented 1 year ago

done, I believe