@@ -15,8 +15,6 @@
*/
package org.icesoft.notify.cloud.core.email;
-import static org.icesoft.util.ObjectUtilities.getValue;
-import static org.icesoft.util.ObjectUtilities.isNotEqual;
import static org.icesoft.util.ObjectUtilities.isNotNull;
import static org.icesoft.util.PreCondition.checkIfIsGreaterThan;
import static org.icesoft.util.PreCondition.checkIfIsNotNull;
@@ -24,21 +22,10 @@
import static org.icesoft.util.StringUtilities.isNotNullAndIsNotEmpty;
import static org.icesoft.util.StringUtilities.isNullOrIsEmpty;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
@@ -46,17 +33,13 @@
import java.util.Properties;
import java.util.Random;
import java.util.Set;
-import java.util.TimeZone;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.DelayQueue;
-import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.json.Json;
import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
@@ -70,16 +53,16 @@
import org.icesoft.notify.cloud.core.AbstractNotificationProvider;
import org.icesoft.notify.cloud.core.CloudNotificationEndpoint;
+import org.icesoft.notify.cloud.core.NotificationData;
import org.icesoft.notify.cloud.core.NotificationEvent;
import org.icesoft.notify.cloud.core.NotificationProvider;
-import org.icesoft.notify.cloud.core.NotificationProviderBlockingQueueListener;
import org.icesoft.util.Configuration;
import org.icesoft.util.NameValuePair;
import org.icesoft.util.SystemConfiguration;
import org.icesoft.util.SystemEnvironmentConfiguration;
import org.icesoft.util.ThreadFactory;
-import org.icesoft.util.concurrent.BlockingQueueActivityReporter;
-import org.icesoft.util.concurrent.BlockingQueueChain;
+import org.icesoft.util.concurrent.NamedReentrantLock;
+import org.icesoft.util.concurrent.Passthrough;
import org.icesoft.util.servlet.ServletContextConfiguration;
public class EmailNotificationProvider
@@ -156,18 +139,12 @@
private static final String TLS = "TLS";
}
- private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss (z)");
- {
- dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
- }
-
private final Set<ScheduledFuture<?>> notificationConsumerSet = new HashSet<ScheduledFuture<?>>();
private final ScheduledThreadPoolExecutor executor;
private final InternetAddress from;
private final String host;
private final int maxConnections;
- private final BlockingQueue<EmailNotification> notificationQueue;
private final String password;
private final int port;
private final String scheme;
@@ -279,29 +256,6 @@
_properties.setProperty("mail.smtps.socketFactory.fallback", "false");
}
session = Session.getInstance(_properties);
- this.notificationQueue =
- new BlockingQueueActivityReporter<EmailNotification>(
- new BlockingQueueChain<EmailNotification>(
- new PriorityBlockingQueue<EmailNotification>(
- 11,
- new Comparator<EmailNotification>() {
- public int compare(
- final EmailNotification notification1, final EmailNotification notification2) {
-
- if (notification1.getPriorityLevel() < notification2.getPriorityLevel()) {
- return 1;
- }
- if (notification1.getPriorityLevel() > notification2.getPriorityLevel()) {
- return -1;
- }
- return 0;
- }
- }
- ),
- new DelayQueue<EmailNotification>()
- )
- ).
- withListener(new NotificationProviderBlockingQueueListener(getName(), getServletContext()));
this.maxConnections =
// throws IllegalArgumentException
checkIfIsGreaterThan(
@@ -314,6 +268,15 @@
new ScheduledThreadPoolExecutor(
maxConnections + 2, new ThreadFactory("APNS Notification Provider Thread", true)
);
+ if (LOGGER.isLoggable(Level.INFO)) {
+ LOGGER.log(Level.INFO, "E-mail Notification Provider is on.");
+ }
+ }
+
+ public void createConsumers(
+ final NamedReentrantLock sharedLock, final Condition sharedCondition,
+ final List<Passthrough<NotificationData>> passthroughList) {
+
for (int i = 0; i < getMaxConnections(); i++) {
String _id = String.format("%016x", new Random().nextInt()).substring(8);
getModifiableNotificationConsumerSet().
@@ -322,20 +285,20 @@
schedule(
new EmailNotificationConsumer(
_id,
- getModifiableNotificationQueue(),
+ sharedLock,
+ sharedCondition,
+ passthroughList,
new EmailConnection(
_id, getSession(), getScheme(), getHost(), getPort(), getUserName(), getPassword(),
getFrom(), this
- )
+ ),
+ this
),
0L,
TimeUnit.SECONDS
)
);
}
- if (LOGGER.isLoggable(Level.INFO)) {
- LOGGER.log(Level.INFO, "E-mail Notification Provider is on.");
- }
}
public Category getCategory() {
@@ -356,15 +319,9 @@
public boolean isValid(final String notifyBackURI) {
boolean _isValid =
- notifyBackURI.startsWith(
- new StringBuilder().append(getProtocolSet().iterator().next()).append(":").toString()
- ) &&
+ notifyBackURI.startsWith(getProtocolSet().iterator().next() + ":") &&
EmailValidator.getInstance().
- isValid(
- notifyBackURI.substring(
- new StringBuilder().append(getProtocolSet().iterator().next()).append(":").length()
- )
- );
+ isValid(notifyBackURI.substring((getProtocolSet().iterator().next() + ":").length()));
if (LOGGER.isLoggable(Level.WARNING)) {
if (!_isValid) {
LOGGER.log(
@@ -378,130 +335,34 @@
public void send(
final Map<Category, Map<String, Object>> categoryToPropertyMap,
- final Set<CloudNotificationEndpoint> cloudNotificationEndpointSet) {
+ final CloudNotificationEndpoint cloudNotificationEndpoint) {
- if (LOGGER.isLoggable(Level.FINE)) {
- LOGGER.log(
- Level.FINE,
- "Sending E-mail Notification with " +
- "Properties '" + categoryToPropertyMap + "' to " +
- "Cloud Notification Endpoints '" + cloudNotificationEndpointSet + "'."
- );
- }
- EmailNotification _notification = constructNotification(categoryToPropertyMap, cloudNotificationEndpointSet);
- if (isNotNull(_notification)) {
- try {
- getModifiableNotificationQueue().
- // throws InterruptedException
- put(_notification);
- if (LOGGER.isLoggable(Level.FINE)) {
- LOGGER.log(
- Level.FINE,
- "Successfully put E-mail Notification '" + _notification + " onto the Queue. " +
- "(Queue size: '" + getModifiableNotificationQueue().size() + "')"
- );
- }
- if (LOGGER.isLoggable(Level.FINE)) {
- for (final CloudNotificationEndpoint _cloudNotificationEndpoint : cloudNotificationEndpointSet) {
- String _batchID = (String)_cloudNotificationEndpoint.getPropertyMap().get("batchID");
- String _pushID = (String)_cloudNotificationEndpoint.getPropertyMap().get("pushID");
- if (isNotNull(_batchID) && isNotNull(_pushID)) {
- LOGGER.log(
- Level.FINE,
- "<short> | " +
- Json.createObjectBuilder().
- add("batchId", _batchID).
- add("pushId", _pushID).
- add("internalQueuePutTime", System.currentTimeMillis()).
- build().
- toString()
- );
- }
- }
- }
- } catch (final InterruptedException exception) {
- if (LOGGER.isLoggable(Level.WARNING)) {
- LOGGER.log(
- Level.WARNING,
- "Interrupted while trying to " +
- "put E-mail Notification '" + _notification + "' on the queue.",
- exception
- );
- }
- }
- }
+ // TODO: Remove this method.
+ throw new UnsupportedOperationException();
}
public void send(
final Map<Category, Map<String, Object>> categoryToPropertyMap,
- final CloudNotificationEndpoint cloudNotificationEndpoint) {
+ final Set<CloudNotificationEndpoint> cloudNotificationEndpointSet) {
- send(
- categoryToPropertyMap,
- new HashSet<CloudNotificationEndpoint>(Arrays.asList(cloudNotificationEndpoint))
- );
+ // TODO: Remove this method.
+ throw new UnsupportedOperationException();
}
@Override
public String toString() {
- return
- new StringBuilder().
- append("EmailNotificationProvider[").
- append(classMembersToString()).
- append("]").
- toString();
+ return "EmailNotificationProvider[" + classMembersToString() + "]";
}
protected String classMembersToString() {
return
- new StringBuilder().
- append("from: '").append(getFrom()).append("', ").
- append("host: '").append(getHost()).append("', ").
- append("password: '").append(getPassword().replaceAll(".", "*")).append("', ").
- append("port: '").append(getPort()).append("', ").
- append("scheme: '").append(getScheme()).append("', ").
- append("session: '").append(getSession()).append("', ").
- append("userName: ").append(getUserName()).append("'").
- toString();
- }
-
- protected EmailNotification constructNotification(
- final Map<Category, Map<String, Object>> categoryToPropertyMap,
- final Set<CloudNotificationEndpoint> cloudNotificationEndpointSet) {
-
- Content _content = getContent(categoryToPropertyMap);
- List<CloudNotificationEndpoint> _cloudNotificationEndpointList =
- new ArrayList<CloudNotificationEndpoint>(cloudNotificationEndpointSet);
- Collections.sort(
- _cloudNotificationEndpointList,
- new Comparator<CloudNotificationEndpoint>() {
- public int compare(
- final CloudNotificationEndpoint cloudNotificationEndpoint1,
- final CloudNotificationEndpoint cloudNotificationEndpoint2) {
-
- return
- cloudNotificationEndpoint1.getNotifyBackURI().
- compareTo(
- cloudNotificationEndpoint2.getNotifyBackURI()
- );
- }
- });
- List<String> _notifyBackURIList = new ArrayList<String>();
- for (final CloudNotificationEndpoint _cloudNotificationEndpoint : _cloudNotificationEndpointList) {
- _notifyBackURIList.add(_cloudNotificationEndpoint.getNotifyBackURI().substring("mailto:".length()));
- }
- LOGGER.info("[Jack] PropertyMap: '" + _cloudNotificationEndpointList.get(0).getPropertyMap() + "'");
- return
- new EmailNotification(
- _cloudNotificationEndpointList,
- _notifyBackURIList,
- (String)getProperty(categoryToPropertyMap, EmailProperty.Name.PERSONAL),
- (String)getProperty(categoryToPropertyMap, EmailProperty.Name.SUBJECT),
- _content.getMessage(),
- _content.getContentType(),
- getValue((Integer)_cloudNotificationEndpointList.get(0).getPropertyMap().get("priorityLevel"), 0),
- (Long)getProperty(categoryToPropertyMap, EmailProperty.Name.DELAY, 0L)
- );
+ "from: '" + getFrom() + "', " +
+ "host: '" + getHost() + "', " +
+ "password: '" + getPassword().replaceAll(".", "*") + "', " +
+ "port: '" + getPort() + "', " +
+ "scheme: '" + getScheme() + "', " +
+ "session: '" + getSession() + "', " +
+ "userName: " + getUserName() + "'";
}
@Override
@@ -528,104 +389,6 @@
super.fireSuccessEvent(event);
}
- protected Content getContent(final Map<Category, Map<String, Object>> categoryToPropertyMap) {
- Content _content = new Content();
- String _template = (String)getProperty(categoryToPropertyMap, EmailProperty.Name.TEMPLATE);
- if (isNotNullAndIsNotEmpty(_template)) {
- try {
- URLConnection _urlConnection = new URL(_template).openConnection();
- BufferedReader _in = new BufferedReader(new InputStreamReader(_urlConnection.getInputStream()));
- StringBuilder _entityBody = new StringBuilder();
- String _line;
- while ((_line = _in.readLine()) != null) {
- _entityBody.append(_line);
- }
- _in.close();
- _content.
- setMessage(
- _entityBody.toString().
- replace(
- "{{subject}}",
- (String) getProperty(categoryToPropertyMap, EmailProperty.Name.SUBJECT)
- ).
- replace(
- "{{detail}}",
- (String) getProperty(categoryToPropertyMap, EmailProperty.Name.DETAIL)
- ).
- replace(
- "{{priority}}",
- (String)
- getValue(
- getProperty(categoryToPropertyMap, EmailProperty.Name.PRIORITY),
- "default"
- )
- ).
- replace(
- "{{time}}",
- (String)
- getValue(
- getProperty(categoryToPropertyMap, EmailProperty.Name.TIME),
- getDateFormat().format(new Date(System.currentTimeMillis()))
- )
- ).
- replace(
- "{{url}}",
- (String) getProperty(categoryToPropertyMap, EmailProperty.Name.URL)
- )
- );
- _content.
- setContentType(
- (String)getProperty(categoryToPropertyMap, EmailProperty.Name.CONTENT_TYPE, "text/html")
- );
- } catch (final MalformedURLException exception) {
- if (LOGGER.isLoggable(Level.WARNING)) {
- LOGGER.log(
- Level.WARNING,
- "Malformed URL for Template: '" + _template + "'. Reverting to plain text format."
- );
- }
- } catch (final IOException exception) {
- if (LOGGER.isLoggable(Level.WARNING)) {
- LOGGER.log(
- Level.WARNING,
- "An I/O error occurred: '" + exception.getMessage() + "'. Reverting to plain text format."
- );
- }
- }
- }
- if (isNullOrIsEmpty(_content.getMessage())) {
- _content.
- setContentType(
- (String) getProperty(categoryToPropertyMap, EmailProperty.Name.CONTENT_TYPE, "text/plain")
- );
- if (_content.getContentType().equals("text/html")) {
- _content.setContentType(_content.getContentType() + "; charset=utf-8");
- }
- if (_content.getContentType().equals("text/plain")) {
- _content.
- setMessage(
- new StringBuilder().
- append(getProperty(categoryToPropertyMap, EmailProperty.Name.DETAIL)).
- toString()
- );
- } else if (_content.getContentType().startsWith("text/html")) {
- _content.
- setMessage(
- new StringBuffer().
- append(getProperty(categoryToPropertyMap, EmailProperty.Name.DETAIL)).
- toString()
- );
- } else {
- // TODO: Log a warning?
- }
- }
- return _content;
- }
-
- protected DateFormat getDateFormat() {
- return dateFormat;
- }
-
protected ScheduledThreadPoolExecutor getExecutor() {
return executor;
}
@@ -646,10 +409,6 @@
return notificationConsumerSet;
}
- protected BlockingQueue<EmailNotification> getModifiableNotificationQueue() {
- return notificationQueue;
- }
-
protected String getPassword() {
return password;
}
@@ -1087,33 +846,4 @@
}
}
}
-
- private static class Content {
- private String contentType;
- private String message;
-
- private Content() {
- // Do nothing.
- }
-
- private String getContentType() {
- return contentType;
- }
-
- private String getMessage() {
- return message;
- }
-
- private void setContentType(final String contentType) {
- if (isNotEqual(getContentType(), contentType)) {
- this.contentType = contentType;
- }
- }
-
- private void setMessage(final String message) {
- if (isNotEqual(getMessage(), message)) {
- this.message = message;
- }
- }
- }
}
|