diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a3aaf761..94091f5bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,19 @@ jobs: java-version: 1.8 - name: Setup Maven run: echo "MAVEN_OPTS='-Xmx2048m'" > ~/.mavenrc + - name: Cache maven repo + uses: actions/cache@v2 + env: + cache-name: cache-maven-repo + with: + # maven files are stored in `~/.m2/repository` on Linux/macOS + path: ~/.m2/repository + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/*.sha1') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- - name: Build with Maven - run: mvn clean verify -U -Pcoverage + run: mvn clean verify --no-transfer-progress -U -Pcoverage - name: Publish coverage run: bash <(curl -s https://codecov.io/bash) diff --git a/bundles/org.eclipse.passage.lic.mail/META-INF/MANIFEST.MF b/bundles/org.eclipse.passage.lic.mail/META-INF/MANIFEST.MF index 944f10f31..cf5ba53d0 100644 --- a/bundles/org.eclipse.passage.lic.mail/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.passage.lic.mail/META-INF/MANIFEST.MF @@ -2,13 +2,12 @@ Manifest-Version: 1.0 Automatic-Module-Name: org.eclipse.passage.lic.mail Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.passage.lic.mail -Bundle-Version: 0.1.0.qualifier +Bundle-Version: 0.2.0.qualifier Bundle-Name: %Bundle-Name Bundle-Vendor: %Bundle-Vendor Bundle-Copyright: %Bundle-Copyright Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: javax.activation;bundle-version="0.0.0", - javax.mail;bundle-version="0.0.0", +Require-Bundle: javax.mail;bundle-version="0.0.0", org.eclipse.osgi.services;bundle-version="0.0.0", org.eclipse.core.runtime;bundle-version="0.0.0", org.eclipse.passage.lic.email;bundle-version="0.0.0";visibility:=reexport diff --git a/bundles/org.eclipse.passage.lic.mail/OSGI-INF/org.eclipse.passage.lic.internal.mail.MailImpl.xml b/bundles/org.eclipse.passage.lic.mail/OSGI-INF/org.eclipse.passage.lic.internal.mail.MailImpl.xml index a3c00f9bb..a5d091969 100644 --- a/bundles/org.eclipse.passage.lic.mail/OSGI-INF/org.eclipse.passage.lic.internal.mail.MailImpl.xml +++ b/bundles/org.eclipse.passage.lic.mail/OSGI-INF/org.eclipse.passage.lic.internal.mail.MailImpl.xml @@ -1,5 +1,5 @@ - + diff --git a/bundles/org.eclipse.passage.lic.mail/src/org/eclipse/passage/lic/internal/mail/MailImpl.java b/bundles/org.eclipse.passage.lic.mail/src/org/eclipse/passage/lic/internal/mail/MailImpl.java index 71cd921c0..9709ed0e2 100644 --- a/bundles/org.eclipse.passage.lic.mail/src/org/eclipse/passage/lic/internal/mail/MailImpl.java +++ b/bundles/org.eclipse.passage.lic.mail/src/org/eclipse/passage/lic/internal/mail/MailImpl.java @@ -15,14 +15,16 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.function.BiConsumer; -import javax.activation.DataHandler; -import javax.activation.DataSource; -import javax.activation.FileDataSource; +import javax.activation.CommandMap; +import javax.activation.MailcapCommandMap; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; +import javax.mail.Part; import javax.mail.Session; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; @@ -32,6 +34,7 @@ import org.eclipse.passage.lic.email.EmailDescriptor; import org.eclipse.passage.lic.email.Mailing; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; /** @@ -42,6 +45,17 @@ */ @Component public class MailImpl implements Mailing { + + @Activate + public void activate() { + //it **may** work "out-of-the-box", but let's declare explicitly to know where to dig + MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap(); + mc.addMailcap("text/plain;; x-java-content-handler=org.apache.geronimo.mail.handlers.TextHandler"); + mc.addMailcap("text/xml;; x-java-content-handler=org.apache.geronimo.mail.handlers.XMLHandler"); + mc.addMailcap("text/html;; x-java-content-handler=org.apache.geronimo.mail.handlers.HtmlHandler"); + mc.addMailcap("message/rfc822;; x-java-content-handler=org.apache.geronimo.mail.handlers.MessageHandler"); + mc.addMailcap("multipart/*;; x-java-content-handler=org.apache.geronimo.mail.handlers.MultipartHandler; x-java-fallback-entry=true"); + } @Override public void writeEml(EmailDescriptor descriptor, OutputStream output, BiConsumer consumerStatus) { @@ -62,27 +76,29 @@ private Message createMessage(EmailDescriptor descriptor) throws MessagingExcept return message; } - private void fulfillMessage(EmailDescriptor descriptor, Message message) throws MessagingException { + private void fulfillMessage(EmailDescriptor descriptor, Message message) throws MessagingException, IOException { Multipart multipart = createBody(descriptor.getBody()); attachFiles(descriptor, multipart); message.setContent(multipart); } private Multipart createBody(String body) throws MessagingException { + Multipart multipart = new MimeMultipart("mixed"); //$NON-NLS-1$ MimeBodyPart content = new MimeBodyPart(); - content.setText(body); - Multipart multipart = new MimeMultipart(); multipart.addBodyPart(content); + content.setText(body, "UTF-8"); return multipart; } - private void attachFiles(EmailDescriptor descriptor, Multipart multipart) throws MessagingException { + private void attachFiles(EmailDescriptor descriptor, Multipart multipart) throws MessagingException, IOException { Iterable attachmentPaths = descriptor.getAttachmentPaths(); for (String path : attachmentPaths) { final File attache = new File(path); MimeBodyPart attachment = new MimeBodyPart(); - DataSource source = new FileDataSource(attache); - attachment.setDataHandler(new DataHandler(source)); + //FIXME: we need to support content types near to attachment path + attachment.setContent(Files.readAllBytes(Paths.get(path)), "application/binary"); + attachment.addHeader("Content-Transfer-Encoding", "base64"); + attachment.setDisposition(Part.ATTACHMENT); attachment.setFileName(attache.getName()); multipart.addBodyPart(attachment); } diff --git a/features/org.eclipse.passage.lic.mail.feature/feature.xml b/features/org.eclipse.passage.lic.mail.feature/feature.xml index 0bdb11c11..5bbd3ea8b 100644 --- a/features/org.eclipse.passage.lic.mail.feature/feature.xml +++ b/features/org.eclipse.passage.lic.mail.feature/feature.xml @@ -14,7 +14,7 @@ diff --git a/releng/org.eclipse.passage.releng/passage.setup b/releng/org.eclipse.passage.releng/passage.setup index 52589bfce..8ea0aa515 100644 --- a/releng/org.eclipse.passage.releng/passage.setup +++ b/releng/org.eclipse.passage.releng/passage.setup @@ -14,7 +14,7 @@ xmlns:setup.targlets="http://www.eclipse.org/oomph/setup/targlets/1.0" xmlns:setup.workingsets="http://www.eclipse.org/oomph/setup/workingsets/1.0" xmlns:workingsets="http://www.eclipse.org/oomph/workingsets/1.0" - xsi:schemaLocation="http://www.eclipse.org/oomph/setup/git/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Git.ecore http://www.eclipse.org/oomph/setup/jdt/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/JDT.ecore http://www.eclipse.org/oomph/setup/mylyn/1.0 index:/models/Mylyn.ecore http://www.eclipse.org/oomph/setup/pde/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/PDE.ecore http://www.eclipse.org/oomph/predicates/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Predicates.ecore http://www.eclipse.org/oomph/setup/projects/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Projects.ecore http://www.eclipse.org/oomph/setup/targlets/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/SetupTarglets.ecore http://www.eclipse.org/oomph/setup/workingsets/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/SetupWorkingSets.ecore http://www.eclipse.org/oomph/workingsets/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/WorkingSets.ecore" + xsi:schemaLocation="http://www.eclipse.org/oomph/setup/git/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Git.ecore http://www.eclipse.org/oomph/setup/jdt/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/JDT.ecore http://www.eclipse.org/oomph/setup/mylyn/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Mylyn.ecore http://www.eclipse.org/oomph/setup/pde/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/PDE.ecore http://www.eclipse.org/oomph/predicates/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Predicates.ecore http://www.eclipse.org/oomph/setup/projects/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Projects.ecore http://www.eclipse.org/oomph/setup/targlets/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/SetupTarglets.ecore http://www.eclipse.org/oomph/setup/workingsets/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/SetupWorkingSets.ecore http://www.eclipse.org/oomph/workingsets/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/WorkingSets.ecore" name="passage" label="Passage"> + url="https://download.eclipse.org/releases/2020-06/"/> Install the tools needed in the IDE to work with the source code for ${scope.project.label} @@ -146,17 +146,17 @@ + url="https://download.eclipse.org/releases/2020-06/"/> + url="https://download.eclipse.org/tools/orbit/downloads/2020-06"/> + url="https://download.eclipse.org/passage/updates/release/0.9.0/lic/"/> + url="https://download.eclipse.org/passage/updates/release/0.9.0/loc/"/> + url="https://download.eclipse.org/passage/updates/release/0.9.0/lbc/"/> + url="https://download.eclipse.org/passage/updates/release/0.9.0/ldc/"/> @@ -192,7 +192,7 @@ xsi:type="setup.targlets:TargletTask"> + activeRepositoryList="2020-06"> + + + + + - + @@ -20,19 +20,19 @@ - + - + - + - + @@ -40,7 +40,7 @@ - + @@ -68,7 +68,7 @@ - + diff --git a/releng/org.eclipse.passage.target/org.eclipse.passage.target.target b/releng/org.eclipse.passage.target/org.eclipse.passage.target.target index 287330205..dda7ffe17 100644 --- a/releng/org.eclipse.passage.target/org.eclipse.passage.target.target +++ b/releng/org.eclipse.passage.target/org.eclipse.passage.target.target @@ -12,7 +12,7 @@ Contributors: ArSysOp - initial API and implementation --> - + @@ -24,7 +24,7 @@ - + @@ -52,7 +52,7 @@ - + diff --git a/tests/org.eclipse.passage.lic.mail.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.passage.lic.mail.tests/META-INF/MANIFEST.MF index 582f90f39..fc1a202a9 100644 --- a/tests/org.eclipse.passage.lic.mail.tests/META-INF/MANIFEST.MF +++ b/tests/org.eclipse.passage.lic.mail.tests/META-INF/MANIFEST.MF @@ -1,19 +1,15 @@ Manifest-Version: 1.0 +Automatic-Module-Name: org.eclipse.passage.lic.mail.tests Bundle-ManifestVersion: 2 +Bundle-SymbolicName: org.eclipse.passage.lic.mail.tests +Bundle-Version: 0.2.0.qualifier Bundle-Name: %Bundle-Name Bundle-Vendor: %Bundle-Vendor Bundle-Copyright: %Bundle-Copyright -Bundle-SymbolicName: org.eclipse.passage.lic.mail.tests;singleton:=true -Bundle-Version: 0.1.0.qualifier -Automatic-Module-Name: org.eclipse.passage.lic.mail.tests +Fragment-Host: org.eclipse.passage.lic.mail Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: org.junit;bundle-version="4.12.0", - javax.mail;bundle-version="0.0.0", - org.eclipse.osgi;bundle-version="0.0.0", - org.eclipse.equinox.registry;bundle-version="3.8.200", - org.eclipse.equinox.common;bundle-version="0.0.0", - org.eclipse.passage.lic.equinox;bundle-version="0.5.0", - org.eclipse.passage.lic.net;bundle-version="0.0.0", - org.eclipse.passage.lic.mail;bundle-version="0.1.0" +Require-Bundle: org.junit;bundle-version="4.12.0" Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.passage.lic.mail.tests +Import-Package: javax.activation;version="1.1.0", + javax.mail;version="1.4.0" diff --git a/tests/org.eclipse.passage.lic.mail.tests/src/org/eclipse/passage/lic/mail/tests/MailImplTest.java b/tests/org.eclipse.passage.lic.mail.tests/src/org/eclipse/passage/lic/mail/tests/MailImplTest.java index f38166ced..de528b4d8 100644 --- a/tests/org.eclipse.passage.lic.mail.tests/src/org/eclipse/passage/lic/mail/tests/MailImplTest.java +++ b/tests/org.eclipse.passage.lic.mail.tests/src/org/eclipse/passage/lic/mail/tests/MailImplTest.java @@ -19,6 +19,7 @@ import static org.junit.Assert.fail; import static org.junit.Assume.assumeNoException; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -30,12 +31,15 @@ import java.util.Collections; import java.util.List; +import javax.activation.CommandMap; +import javax.activation.MailcapCommandMap; import javax.mail.internet.AddressException; import org.eclipse.passage.lic.email.EmailDescriptor; import org.eclipse.passage.lic.email.Mailing; import org.eclipse.passage.lic.internal.mail.MailImpl; import org.junit.After; +import org.junit.BeforeClass; import org.junit.Test; public class MailImplTest { @@ -49,24 +53,43 @@ public class MailImplTest { private static final String MAIL_ATTACHMENT_CONTENT = "Content by TimeStamp:"; //$NON-NLS-1$ private Path fileAttachmentPath; + private static String resolveOutputDirName() { + return System.getProperty("project.build.directory", + System.getProperty("user.dir") + File.separator + "target"); + } + + @BeforeClass + public static void initialize() { + //need this extra setup to avoid java.lang.AssertionError: no object DCH for MIME type multipart/mixed; + MailImpl mailing = new MailImpl(); + mailing.activate(); + System.out.println("multipart/*" + ' ' + + ((MailcapCommandMap) CommandMap.getDefaultCommandMap()).createDataContentHandler("multipart/*")); + } + @Test public void shouldCreateEmlByParametersPositiveTest() { - Mailing mailing = new MailImpl(); + MailImpl mailing = new MailImpl(); String attachment = createAttachment(); assertFalse(attachment.isEmpty()); - EmailDescriptor mailDescriptor = mailing.createMail(MAIL_TO, MAIL_FROM, MAIL_SUBJECT, - MAIL_BODY, Collections.singleton(attachment)); + EmailDescriptor mailDescriptor = mailing.createMail(MAIL_TO, MAIL_FROM, MAIL_SUBJECT, MAIL_BODY, + Collections.singleton(attachment)); assertNotNull(mailDescriptor); try (FileOutputStream fileOutput = new FileOutputStream(MAIL_FILE_OUT)) { - mailing.writeEml(mailDescriptor, fileOutput, (m, t) -> fail()); + mailing.writeEml(mailDescriptor, fileOutput, (m, t) -> failure(m, t)); } catch (IOException e) { assumeNoException(e); } } + private void failure(String message, Throwable t) { + t.printStackTrace(); + fail(message); + } + @Test - public void shouldCreateEmlByParametersNagativeTest() { - Mailing mailing = new MailImpl(); + public void shouldCreateEmlByParametersNegativeTest() { + MailImpl mailing = new MailImpl(); String attachment = createAttachment(); assertFalse(attachment.isEmpty()); EmailDescriptor mailDescriptor = mailing.createMail("", "", "", "", Collections.singleton(attachment)); @@ -90,9 +113,9 @@ public void shouldFailWithNullAttachmentTest() { } private String createAttachment() { - String userHome = System.getProperty("user.home"); + String userDir = resolveOutputDirName(); try { - Path createFile = Files.createFile(Paths.get(userHome, MAIL_ATTACHMENT)); + Path createFile = Files.createFile(Paths.get(userDir, MAIL_ATTACHMENT)); List content = new ArrayList<>(); String attachmentContent = new String(MAIL_ATTACHMENT_CONTENT + System.currentTimeMillis()); content.add(attachmentContent);