JsoupAttachImageInliner.java

1
package fr.sii.ogham.html.inliner.impl.jsoup;
2
3
import static fr.sii.ogham.email.attachment.ContentDisposition.INLINE;
4
import static fr.sii.ogham.html.inliner.ImageInlinerConstants.INLINED_ATTR;
5
import static fr.sii.ogham.html.inliner.ImageInlinerConstants.InlineModes.ATTACH;
6
import static fr.sii.ogham.html.inliner.impl.jsoup.ImageInlineUtils.isInlineModeAllowed;
7
import static java.text.MessageFormat.format;
8
9
import java.util.ArrayList;
10
import java.util.List;
11
12
import org.jsoup.Jsoup;
13
import org.jsoup.nodes.Document;
14
import org.jsoup.nodes.Element;
15
import org.jsoup.select.Elements;
16
17
import fr.sii.ogham.core.id.generator.IdGenerator;
18
import fr.sii.ogham.core.resource.ByteResource;
19
import fr.sii.ogham.email.attachment.Attachment;
20
import fr.sii.ogham.html.inliner.ContentWithImages;
21
import fr.sii.ogham.html.inliner.ImageInliner;
22
import fr.sii.ogham.html.inliner.ImageInlinerConstants;
23
import fr.sii.ogham.html.inliner.ImageInlinerConstants.InlineModes;
24
import fr.sii.ogham.html.inliner.ImageResource;
25
26
/**
27
 * Image inliner that loads the image and attaches it to the mail. The image is
28
 * referenced using a content ID. The content ID is automatically generated.
29
 * 
30
 * <p>
31
 * The inlining using attach mode is only applied if the attribute
32
 * {@link ImageInlinerConstants#INLINE_MODE_ATTR} is set to
33
 * {@link InlineModes#ATTACH}.
34
 * </p>
35
 * 
36
 * @author Aurélien Baudet
37
 *
38
 */
39
public class JsoupAttachImageInliner implements ImageInliner {
40
	private static final String CONTENT_ID = "<{0}>";
41
	private static final String SRC_ATTR = "src";
42
	private static final String SRC_VALUE = "cid:{0}";
43
	private static final String IMG_SELECTOR = "img[src=\"{0}\"]";
44
45
	private IdGenerator idGenerator;
46
47
	public JsoupAttachImageInliner(IdGenerator idGenerator) {
48
		super();
49
		this.idGenerator = idGenerator;
50
	}
51
52
	@Override
53
	public ContentWithImages inline(String htmlContent, List<ImageResource> images) {
54
		Document doc = Jsoup.parse(htmlContent);
55
		List<Attachment> attachments = new ArrayList<>(images.size());
56
		for (ImageResource image : images) {
57
			// search all images in the HTML with the provided path or URL that
58
			// are not skipped
59
			Elements imgs = getImagesToAttach(doc, image);
60 3 1. inline : negated conditional → NO_COVERAGE
2. inline : negated conditional → KILLED
3. inline : negated conditional → KILLED
			if (!imgs.isEmpty()) {
61
				String contentId = idGenerator.generate(image.getName());
62
				// generate attachment
63
				Attachment attachment = new Attachment(new ByteResource(image.getName(), image.getContent()), null, INLINE, format(CONTENT_ID, contentId));
64
				// update the HTML to use the generated content id instead of
65
				// the path or URL
66
				for (Element img : imgs) {
67
					img.attr(SRC_ATTR, format(SRC_VALUE, contentId));
68
					img.attr(INLINED_ATTR, true);
69
				}
70
				attachments.add(attachment);
71
			}
72
		}
73 3 1. inline : replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::inline → NO_COVERAGE
2. inline : replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::inline → KILLED
3. inline : replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::inline → KILLED
		return new ContentWithImages(doc.outerHtml(), attachments);
74
	}
75
76
	private static Elements getImagesToAttach(Document doc, ImageResource image) {
77
		Elements imgs = doc.select(format(IMG_SELECTOR, image.getSrcUrl()));
78
		Elements found = new Elements();
79
		for (Element img : imgs) {
80
			// skip images that have skip-attach attribute
81 3 1. getImagesToAttach : negated conditional → NO_COVERAGE
2. getImagesToAttach : negated conditional → KILLED
3. getImagesToAttach : negated conditional → KILLED
			if (isInlineModeAllowed(img, ATTACH)) {
82
				found.add(img);
83
			}
84
		}
85 3 1. getImagesToAttach : replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::getImagesToAttach → NO_COVERAGE
2. getImagesToAttach : replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::getImagesToAttach → KILLED
3. getImagesToAttach : replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::getImagesToAttach → KILLED
		return found;
86
	}
87
88
}

Mutations

60

1.1
Location : inline
Killed by : oghamcore.ut.html.inliner.impl.JsoupAttachImageInlinerTest.withImages(oghamcore.ut.html.inliner.impl.JsoupAttachImageInlinerTest)
negated conditional → KILLED

2.2
Location : inline
Killed by : none
negated conditional → NO_COVERAGE

3.3
Location : inline
Killed by : oghamall.it.html.translator.JsoupInlineImageTranslatorTest.skipExternalImages(oghamall.it.html.translator.JsoupInlineImageTranslatorTest)
negated conditional → KILLED

73

1.1
Location : inline
Killed by : oghamcore.ut.html.inliner.impl.JsoupAttachImageInlinerTest.withImages(oghamcore.ut.html.inliner.impl.JsoupAttachImageInlinerTest)
replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::inline → KILLED

2.2
Location : inline
Killed by : oghamall.it.html.translator.JsoupInlineImageTranslatorTest.skipExternalImages(oghamall.it.html.translator.JsoupInlineImageTranslatorTest)
replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::inline → KILLED

3.3
Location : inline
Killed by : none
replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::inline → NO_COVERAGE

81

1.1
Location : getImagesToAttach
Killed by : oghamall.it.html.translator.JsoupInlineImageTranslatorTest.skipExternalImages(oghamall.it.html.translator.JsoupInlineImageTranslatorTest)
negated conditional → KILLED

2.2
Location : getImagesToAttach
Killed by : none
negated conditional → NO_COVERAGE

3.3
Location : getImagesToAttach
Killed by : oghamcore.ut.html.inliner.impl.JsoupAttachImageInlinerTest.withImages(oghamcore.ut.html.inliner.impl.JsoupAttachImageInlinerTest)
negated conditional → KILLED

85

1.1
Location : getImagesToAttach
Killed by : none
replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::getImagesToAttach → NO_COVERAGE

2.2
Location : getImagesToAttach
Killed by : oghamall.it.html.translator.JsoupInlineImageTranslatorTest.skipExternalImages(oghamall.it.html.translator.JsoupInlineImageTranslatorTest)
replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::getImagesToAttach → KILLED

3.3
Location : getImagesToAttach
Killed by : oghamcore.ut.html.inliner.impl.JsoupAttachImageInlinerTest.withImages(oghamcore.ut.html.inliner.impl.JsoupAttachImageInlinerTest)
replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupAttachImageInliner::getImagesToAttach → KILLED

Active mutators

Tests examined


Report generated by PIT OGHAM