Project

General

Profile

1
package eu.dnetlib.msro.notification;
2

    
3
import java.io.StringReader;
4
import java.util.Date;
5
import java.util.HashMap;
6
import java.util.Map;
7
import java.util.Properties;
8
import java.util.concurrent.BlockingQueue;
9
import java.util.concurrent.LinkedBlockingQueue;
10

    
11
import javax.annotation.Resource;
12
import javax.mail.Authenticator;
13
import javax.mail.Message;
14
import javax.mail.MessagingException;
15
import javax.mail.PasswordAuthentication;
16
import javax.mail.Session;
17
import javax.mail.Transport;
18
import javax.mail.internet.InternetAddress;
19
import javax.mail.internet.MimeMessage;
20

    
21
import org.antlr.stringtemplate.StringTemplate;
22
import org.apache.commons.lang3.StringUtils;
23
import org.apache.commons.logging.Log;
24
import org.apache.commons.logging.LogFactory;
25
import org.dom4j.Document;
26
import org.dom4j.io.SAXReader;
27
import org.springframework.beans.factory.annotation.Required;
28

    
29
import com.google.common.base.Splitter;
30

    
31
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
32
import eu.dnetlib.msro.workflows.procs.WorkflowProcess;
33
import eu.dnetlib.msro.workflows.procs.WorkflowProcess.Status;
34
import eu.dnetlib.rmi.enabling.ISLookUpService;
35

    
36
public class EmailDispatcher {
37

    
38
	private String from;
39
	private String fromName;
40
	private String cc;
41
	private String smtpHost;
42
	private int smtpPort = 587;
43
	private String smtpUser;
44
	private String smtpPassword;
45
	private String baseUrl;
46
	private String infrastructure;
47

    
48
	private static final Log log = LogFactory.getLog(EmailDispatcher.class);
49

    
50
	@Resource
51
	private UniqueServiceLocator serviceLocator;
52

    
53
	private final BlockingQueue<Message> queue = new LinkedBlockingQueue<Message>();
54

    
55
	public void sendMail(final String to, final String subject, final String message) {
56
		try {
57
			final Session session = Session.getInstance(obtainProperties(), obtainAuthenticator());
58

    
59
			final MimeMessage mimeMessage = new MimeMessage(session);
60
			mimeMessage.setFrom(new InternetAddress(this.from, this.fromName));
61
			mimeMessage.setSubject(subject);
62
			mimeMessage.setContent(message, "text/html; charset=utf-8");
63
			mimeMessage.setSentDate(new Date());
64

    
65
			mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
66

    
67
			if ((this.cc != null) && !this.cc.isEmpty()) {
68
				for (final String aCC : Splitter.on(",").omitEmptyStrings().trimResults().split(getCc())) {
69
					mimeMessage.addRecipient(Message.RecipientType.CC, new InternetAddress(aCC));
70
				}
71
			}
72

    
73
			this.queue.add(mimeMessage);
74

    
75
			log.info("Mail to " + to + " in queue");
76
		} catch (final Exception e) {
77
			log.error("Error sending mail", e);
78
		}
79
	}
80

    
81
	private String applyTemplate(final String template, final WorkflowProcess proc) {
82
		final StringTemplate st = new StringTemplate(template);
83
		st.setAttribute("proc", proc);
84
		st.setAttribute("baseUrl", this.baseUrl);
85
		st.setAttribute("infrastructure", this.infrastructure);
86
		return st.toString();
87
	}
88

    
89
	public void processMailQueue() {
90
		while (true) {
91
			final Message message = this.queue.poll();
92
			if (message == null) {
93
				return;
94
			} else {
95
				try {
96
					log.info("Sending mail...");
97
					Transport.send(message);
98
					log.info("...sent");
99
				} catch (final MessagingException e) {
100
					log.error("Error sending email", e);
101
					this.queue.add(message);
102
					return;
103
				}
104
			}
105
		}
106
	}
107

    
108
	public void sendMails(final WorkflowProcess proc) {
109

    
110
		final SAXReader reader = new SAXReader();
111
		final Map<String, Document> emailProfiles = new HashMap<>();
112

    
113
		try {
114

    
115
			this.serviceLocator
116
					.getService(ISLookUpService.class)
117
					.quickSearchProfile("for $x in collection('/db/DRIVER/WorkflowDSResources/WorkflowDSResourceType') " +
118
							"where $x//RESOURCE_IDENTIFIER/@value='" + proc.getProfileId() + "' " +
119
							"return $x//NOTIFICATIONS/EMAIL/concat(@condition , ' @@@ ',  @messageProfileId, ' @@@ ', @address)")
120
					.forEach(s -> {
121
						final String[] arr = s.split("@@@");
122
						if (StringUtils.isNoneBlank(arr[0].trim())) {
123
							final NotificationCondition condition = NotificationCondition.valueOf(arr[0].trim());
124
							final String emailProfileId = arr[1].trim();
125
							final String to = arr[2].trim();
126

    
127
							if (condition == NotificationCondition.ALWAYS ||
128
									(condition == NotificationCondition.ONLY_FAILED && proc.getStatus() == Status.FAILURE) ||
129
									(condition == NotificationCondition.ONLY_SUCCESS && proc.getStatus() == Status.SUCCESS)) {
130
								try {
131
									if (!emailProfiles.containsKey(emailProfileId)) {
132
										final String profile = this.serviceLocator.getService(ISLookUpService.class).getResourceProfile(emailProfileId);
133
										final Document doc = reader.read(new StringReader(profile));
134
										emailProfiles.put(emailProfileId, doc);
135
									}
136
									final String subject = applyTemplate(emailProfiles.get(emailProfileId).valueOf("//SUBJECT_TEMPLATE").trim(), proc);
137
									final String message = applyTemplate(emailProfiles.get(emailProfileId).valueOf("//EMAIL_TEMPLATE").trim(), proc);
138

    
139
									sendMail(to, subject, message);
140

    
141
								} catch (final Exception e) {
142
									log.error("Error sending mail to " + to, e);
143
								}
144
							}
145
						}
146
					});
147
		} catch (final Throwable e) {
148
			log.error("Error generating sending mails for process: " + proc.getId(), e);
149
		}
150

    
151
	}
152

    
153
	private Properties obtainProperties() {
154
		final Properties props = new Properties();
155
		props.put("mail.transport.protocol", "smtp");
156
		props.put("mail.smtp.host", this.smtpHost);
157
		props.put("mail.smtp.port", this.smtpPort);
158
		props.put("mail.smtp.auth", Boolean.toString((this.smtpUser != null) && !this.smtpUser.isEmpty()));
159
		return props;
160
	}
161

    
162
	private Authenticator obtainAuthenticator() {
163
		if ((this.smtpUser == null) || this.smtpUser.isEmpty()) { return null; }
164

    
165
		return new Authenticator() {
166

    
167
			private final PasswordAuthentication authentication = new PasswordAuthentication(EmailDispatcher.this.smtpUser, EmailDispatcher.this.smtpPassword);
168

    
169
			@Override
170
			protected PasswordAuthentication getPasswordAuthentication() {
171
				return this.authentication;
172
			}
173

    
174
		};
175
	}
176

    
177
	public String getFrom() {
178
		return this.from;
179
	}
180

    
181
	@Required
182
	public void setFrom(final String from) {
183
		this.from = from;
184
	}
185

    
186
	public String getFromName() {
187
		return this.fromName;
188
	}
189

    
190
	@Required
191
	public void setFromName(final String fromName) {
192
		this.fromName = fromName;
193
	}
194

    
195
	public String getCc() {
196
		return this.cc;
197
	}
198

    
199
	@Required
200
	public void setCc(final String cc) {
201
		this.cc = cc;
202
	}
203

    
204
	public String getSmtpHost() {
205
		return this.smtpHost;
206
	}
207

    
208
	@Required
209
	public void setSmtpHost(final String smtpHost) {
210
		this.smtpHost = smtpHost;
211
	}
212

    
213
	public int getSmtpPort() {
214
		return this.smtpPort;
215
	}
216

    
217
	public void setSmtpPort(final int smtpPort) {
218
		this.smtpPort = smtpPort;
219
	}
220

    
221
	public String getSmtpUser() {
222
		return this.smtpUser;
223
	}
224

    
225
	public void setSmtpUser(final String smtpUser) {
226
		this.smtpUser = smtpUser;
227
	}
228

    
229
	public String getSmtpPassword() {
230
		return this.smtpPassword;
231
	}
232

    
233
	public void setSmtpPassword(final String smtpPassword) {
234
		this.smtpPassword = smtpPassword;
235
	}
236

    
237
	public String getBaseUrl() {
238
		return this.baseUrl;
239
	}
240

    
241
	@Required
242
	public void setBaseUrl(final String baseUrl) {
243
		this.baseUrl = baseUrl;
244
	}
245

    
246
	public String getInfrastructure() {
247
		return this.infrastructure;
248
	}
249

    
250
	@Required
251
	public void setInfrastructure(final String infrastructure) {
252
		this.infrastructure = infrastructure;
253
	}
254

    
255
}
(1-1/2)