Skip to content

Commit e9b18e7

Browse files
lesson 11 hw
1 parent fbbc628 commit e9b18e7

13 files changed

Lines changed: 199 additions & 91 deletions

File tree

services/mail-api/src/main/java/ru/javaops/masterjava/service/mail/MailWSClient.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
package ru.javaops.masterjava.service.mail;
22

3-
import com.google.common.base.Splitter;
4-
import com.google.common.collect.ImmutableSet;
5-
import com.google.common.collect.Iterables;
63
import com.google.common.io.Resources;
74
import lombok.extern.slf4j.Slf4j;
85
import ru.javaops.web.WebStateException;
@@ -56,11 +53,6 @@ private static MailService getPort() {
5653
return WS_CLIENT.getPort(new MTOMFeature(1024));
5754
}
5855

59-
public static Set<Addressee> split(String addressees) {
60-
Iterable<String> split = Splitter.on(',').trimResults().omitEmptyStrings().split(addressees);
61-
return ImmutableSet.copyOf(Iterables.transform(split, Addressee::new));
62-
}
63-
6456
public static WsClient.HostConfig getHostConfig() {
6557
return WS_CLIENT.getHostConfig();
6658
}

services/mail-api/src/main/java/ru/javaops/masterjava/service/mail/util/Attachments.java

Lines changed: 0 additions & 45 deletions
This file was deleted.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package ru.javaops.masterjava.service.mail.util;
2+
3+
import com.google.common.base.Splitter;
4+
import com.google.common.collect.ImmutableSet;
5+
import com.google.common.collect.Iterables;
6+
import com.sun.istack.NotNull;
7+
import lombok.AllArgsConstructor;
8+
import lombok.Data;
9+
import org.apache.commons.io.input.CloseShieldInputStream;
10+
import ru.javaops.masterjava.service.mail.Addressee;
11+
import ru.javaops.masterjava.service.mail.Attach;
12+
13+
import javax.activation.DataHandler;
14+
import javax.activation.DataSource;
15+
import java.io.*;
16+
import java.util.AbstractMap.SimpleImmutableEntry;
17+
import java.util.List;
18+
import java.util.Set;
19+
import java.util.stream.Collectors;
20+
21+
public class MailUtils {
22+
23+
public static Set<Addressee> split(String addressees) {
24+
Iterable<String> split = Splitter.on(',').trimResults().omitEmptyStrings().split(addressees);
25+
return ImmutableSet.copyOf(Iterables.transform(split, Addressee::new));
26+
}
27+
28+
@Data
29+
@AllArgsConstructor
30+
public static class MailObject implements Serializable {
31+
private @NotNull String users;
32+
private String subject;
33+
private @NotNull String body;
34+
// http://stackoverflow.com/questions/521171/a-java-collection-of-value-pairs-tuples
35+
private List<SimpleImmutableEntry<String, byte[]>> attaches;
36+
}
37+
38+
public static List<Attach> getAttaches(List<SimpleImmutableEntry<String, byte[]>> attaches) {
39+
return attaches.stream().map(a -> getAttach(a.getKey(), a.getValue())).collect(Collectors.toList());
40+
}
41+
42+
public static Attach getAttach(String name, byte[] attachData) {
43+
return new Attach(name, new DataHandler((ProxyDataSource) () -> new ByteArrayInputStream(attachData)));
44+
}
45+
46+
public static Attach getAttach(String name, InputStream inputStream) {
47+
// http://stackoverflow.com/questions/2830561/how-to-convert-an-inputstream-to-a-datahandler
48+
// http://stackoverflow.com/a/5924019/548473
49+
return new Attach(name, new DataHandler((ProxyDataSource) () -> new CloseShieldInputStream(inputStream)));
50+
}
51+
52+
public interface ProxyDataSource extends DataSource {
53+
@Override
54+
default OutputStream getOutputStream() throws IOException {
55+
throw new UnsupportedOperationException("Not implemented");
56+
}
57+
58+
@Override
59+
default String getContentType() {
60+
return "application/octet-stream";
61+
}
62+
63+
@Override
64+
default String getName() {
65+
return "";
66+
}
67+
}
68+
}

services/mail-service/pom.xml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,17 @@
9090
<artifactId>jersey-bean-validation</artifactId>
9191
<version>2.25.1</version>
9292
</dependency>
93+
<dependency>
94+
<groupId>org.glassfish.jersey.media</groupId>
95+
<artifactId>jersey-media-multipart</artifactId>
96+
<version>2.25.1</version>
97+
<exclusions>
98+
<exclusion>
99+
<groupId>org.jvnet.mimepull</groupId>
100+
<artifactId>mimepull</artifactId>
101+
</exclusion>
102+
</exclusions>
103+
</dependency>
93104

94105
<dependency>
95106
<groupId>org.apache.activemq</groupId>
@@ -104,4 +115,4 @@
104115
</exclusions>
105116
</dependency>
106117
</dependencies>
107-
</project>
118+
</project>

services/mail-service/src/main/java/ru/javaops/masterjava/service/mail/MailServiceExecutor.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import lombok.extern.slf4j.Slf4j;
44
import one.util.streamex.StreamEx;
5+
import ru.javaops.masterjava.service.mail.util.MailUtils;
6+
import ru.javaops.masterjava.service.mail.util.MailUtils.MailObject;
7+
import ru.javaops.web.WebStateException;
58

69
import java.util.ArrayList;
710
import java.util.List;
@@ -63,4 +66,17 @@ private GroupResult cancelWithFail(String cause) {
6366
}
6467
}.call();
6568
}
69+
70+
public static void sendAsync(MailObject mailObject) {
71+
Set<Addressee> addressees = MailUtils.split(mailObject.getUsers());
72+
addressees.forEach(addressee ->
73+
mailExecutor.submit(() -> {
74+
try {
75+
MailSender.sendTo(addressee, mailObject.getSubject(), mailObject.getBody(), MailUtils.getAttaches(mailObject.getAttaches()));
76+
} catch (WebStateException e) {
77+
// already logged
78+
}
79+
})
80+
);
81+
}
6682
}

services/mail-service/src/main/java/ru/javaops/masterjava/service/mail/jms/JmsListener.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package ru.javaops.masterjava.service.mail.jms;
22

33
import lombok.extern.slf4j.Slf4j;
4+
import org.apache.activemq.ActiveMQConnectionFactory;
5+
import ru.javaops.masterjava.service.mail.MailServiceExecutor;
6+
import ru.javaops.masterjava.service.mail.util.MailUtils.MailObject;
47

58
import javax.jms.*;
69
import javax.naming.InitialContext;
@@ -18,8 +21,9 @@ public class JmsListener implements ServletContextListener {
1821
public void contextInitialized(ServletContextEvent sce) {
1922
try {
2023
InitialContext initCtx = new InitialContext();
21-
QueueConnectionFactory connectionFactory =
22-
(QueueConnectionFactory) initCtx.lookup("java:comp/env/jms/ConnectionFactory");
24+
ActiveMQConnectionFactory connectionFactory =
25+
(ActiveMQConnectionFactory) initCtx.lookup("java:comp/env/jms/ConnectionFactory");
26+
connectionFactory.setTrustAllPackages(true);
2327
connection = connectionFactory.createQueueConnection();
2428
QueueSession queueSession = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
2529
Queue queue = (Queue) initCtx.lookup("java:comp/env/jms/queue/MailQueue");
@@ -30,11 +34,11 @@ public void contextInitialized(ServletContextEvent sce) {
3034
try {
3135
while (!Thread.interrupted()) {
3236
Message m = receiver.receive();
33-
// TODO implement mail sending
34-
if (m instanceof TextMessage) {
35-
TextMessage tm = (TextMessage) m;
36-
String text = tm.getText();
37-
log.info(String.format("Received TextMessage with text '%s'.", text));
37+
if (m instanceof ObjectMessage) {
38+
ObjectMessage om = (ObjectMessage) m;
39+
MailObject mailObject = (MailObject) om.getObject();
40+
log.info("Received MailObject {}", mailObject);
41+
MailServiceExecutor.sendAsync(mailObject);
3842
}
3943
}
4044
} catch (Exception e) {
@@ -60,4 +64,4 @@ public void contextDestroyed(ServletContextEvent sce) {
6064
listenerThread.interrupt();
6165
}
6266
}
63-
}
67+
}
Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
package ru.javaops.masterjava.service.mail.rest;
22

33

4+
import com.google.common.collect.ImmutableList;
5+
import org.glassfish.jersey.media.multipart.BodyPartEntity;
6+
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
7+
import org.glassfish.jersey.media.multipart.FormDataParam;
48
import org.hibernate.validator.constraints.NotBlank;
9+
import ru.javaops.masterjava.service.mail.Attach;
510
import ru.javaops.masterjava.service.mail.GroupResult;
611
import ru.javaops.masterjava.service.mail.MailServiceExecutor;
7-
import ru.javaops.masterjava.service.mail.MailWSClient;
12+
import ru.javaops.masterjava.service.mail.util.MailUtils;
813
import ru.javaops.web.WebStateException;
914

15+
import javax.activation.DataHandler;
1016
import javax.ws.rs.*;
1117
import javax.ws.rs.core.MediaType;
12-
import java.util.Collections;
18+
import java.io.UnsupportedEncodingException;
19+
import java.util.List;
1320

1421
@Path("/")
1522
public class MailRS {
@@ -21,12 +28,30 @@ public String test() {
2128
}
2229

2330
@POST
24-
@Path("send")
31+
@Path("/send")
2532
@Produces(MediaType.APPLICATION_JSON)
26-
public GroupResult send(@NotBlank @FormParam("users") String users,
27-
@FormParam("subject") String subject,
28-
@NotBlank @FormParam("body") String body) throws WebStateException {
33+
@Consumes(MediaType.MULTIPART_FORM_DATA)
34+
public GroupResult send(@NotBlank @FormDataParam("users") String users,
35+
@FormDataParam("subject") String subject,
36+
@NotBlank @FormDataParam("body") String body,
37+
@FormDataParam("attach") FormDataBodyPart attachBodyPart) throws WebStateException {
2938

30-
return MailServiceExecutor.sendBulk(MailWSClient.split(users), subject, body, Collections.emptyList());
39+
final List<Attach> attaches;
40+
String attachName = attachBodyPart.getContentDisposition().getFileName();
41+
42+
if (attachName.isEmpty()) {
43+
attaches = ImmutableList.of();
44+
} else {
45+
try {
46+
// UTF-8 encoding workaround: https://java.net/jira/browse/JERSEY-3032
47+
String utf8name = new String(attachName.getBytes("ISO8859_1"), "UTF-8");
48+
BodyPartEntity bodyPartEntity = ((BodyPartEntity) attachBodyPart.getEntity());
49+
50+
attaches = ImmutableList.of(new Attach(utf8name, new DataHandler((MailUtils.ProxyDataSource) bodyPartEntity::getInputStream)));
51+
} catch (UnsupportedEncodingException e) {
52+
throw new IllegalStateException(e);
53+
}
54+
}
55+
return MailServiceExecutor.sendBulk(MailUtils.split(users), subject, body, attaches);
3156
}
3257
}

services/mail-service/src/main/java/ru/javaops/masterjava/service/mail/rest/MailRestConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package ru.javaops.masterjava.service.mail.rest;
22

3+
import org.glassfish.jersey.media.multipart.MultiPartFeature;
34
import org.glassfish.jersey.server.ResourceConfig;
45
import org.slf4j.bridge.SLF4JBridgeHandler;
56

@@ -13,5 +14,6 @@ public MailRestConfig() {
1314
// http://stackoverflow.com/questions/4121722
1415
SLF4JBridgeHandler.install();
1516
packages("ru.javaops.masterjava.service.mail.rest");
17+
register(MultiPartFeature.class);
1618
}
1719
}

services/mail-service/src/main/resources/mailWsHandlers.xml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,5 @@
88
<handler-name>SoapStatisticHandler</handler-name>
99
<handler-class>ru.javaops.web.handler.SoapStatisticHandler</handler-class>
1010
</handler>
11-
<handler>
12-
<handler-name>MailSecurityHandler</handler-name>
13-
<handler-class>ru.javaops.masterjava.service.mail.MailHandlers$SecurityHandler</handler-class>
14-
</handler>
1511
</handler-chain>
16-
</handler-chains>
12+
</handler-chains>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
4+
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
5+
version="3.1">
6+
7+
<security-constraint>
8+
<web-resource-collection>
9+
<web-resource-name>mailService</web-resource-name>
10+
<url-pattern>/mailService</url-pattern>
11+
</web-resource-collection>
12+
<auth-constraint>
13+
<role-name>tomcat</role-name>
14+
</auth-constraint>
15+
</security-constraint>
16+
17+
<login-config>
18+
<auth-method>BASIC</auth-method>
19+
<realm-name>Tomcat basic auth</realm-name>
20+
</login-config>
21+
22+
<security-role>
23+
<role-name>tomcat</role-name>
24+
</security-role>
25+
</web-app>

0 commit comments

Comments
 (0)