/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.pop.notifications.internal.messaging;
import com.liferay.mail.kernel.model.Account;
import com.liferay.petra.mail.MailEngine;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.messaging.BaseMessageListener;
import com.liferay.portal.kernel.messaging.DestinationNames;
import com.liferay.portal.kernel.module.framework.ModuleServiceLifecycle;
import com.liferay.portal.kernel.pop.MessageListener;
import com.liferay.portal.kernel.pop.MessageListenerException;
import com.liferay.portal.kernel.scheduler.SchedulerEngineHelper;
import com.liferay.portal.kernel.scheduler.SchedulerEntry;
import com.liferay.portal.kernel.scheduler.SchedulerEntryImpl;
import com.liferay.portal.kernel.scheduler.TimeUnit;
import com.liferay.portal.kernel.scheduler.Trigger;
import com.liferay.portal.kernel.scheduler.TriggerFactory;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.pop.notifications.internal.MessageListenerWrapper;
import com.liferay.portal.util.PropsValues;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.mail.Address;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
* @author Brian Wing Shun Chan
*/
@Component(immediate = true, service = POPNotificationsMessageListener.class)
public class POPNotificationsMessageListener extends BaseMessageListener {
@Activate
@Modified
protected void activate() {
if (PropsValues.POP_SERVER_NOTIFICATIONS_ENABLED) {
Class<?> clazz = getClass();
String className = clazz.getName();
Trigger trigger = _triggerFactory.createTrigger(
className, className, null, null, 1, TimeUnit.MINUTE);
SchedulerEntry schedulerEntry = new SchedulerEntryImpl(
className, trigger);
_schedulerEngineHelper.register(
this, schedulerEntry, DestinationNames.SCHEDULER_DISPATCH);
}
}
@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.RELUCTANT,
service = MessageListener.class
)
protected void addMessageListener(MessageListener messageListener) {
MessageListenerWrapper messageListenerWrapper =
new MessageListenerWrapper(messageListener);
_messageListenerWrappers.put(messageListener, messageListenerWrapper);
}
@Deactivate
protected void deactivate() {
if (PropsValues.POP_SERVER_NOTIFICATIONS_ENABLED) {
_schedulerEngineHelper.unregister(this);
}
}
@Override
protected void doReceive(
com.liferay.portal.kernel.messaging.Message message)
throws MessagingException {
Store store = null;
try {
store = getStore();
Folder inboxFolder = getInboxFolder(store);
if (inboxFolder == null) {
return;
}
try {
Message[] messages = inboxFolder.getMessages();
if (messages == null) {
return;
}
if (_log.isDebugEnabled()) {
_log.debug("Deleting messages");
}
inboxFolder.setFlags(
messages, new Flags(Flags.Flag.DELETED), true);
notifyMessageListeners(messages);
}
finally {
inboxFolder.close(true);
}
}
finally {
if (store != null) {
store.close();
}
}
}
protected String getEmailAddress(Address[] addresses) {
if (ArrayUtil.isEmpty(addresses)) {
return StringPool.BLANK;
}
InternetAddress internetAddress = (InternetAddress)addresses[0];
return internetAddress.getAddress();
}
protected Folder getInboxFolder(Store store) throws MessagingException {
Folder defaultFolder = store.getDefaultFolder();
Folder[] folders = defaultFolder.list();
if (folders.length == 0) {
throw new MessagingException("Inbox not found");
}
Folder inboxFolder = folders[0];
inboxFolder.open(Folder.READ_WRITE);
return inboxFolder;
}
protected Store getStore() throws MessagingException {
Session session = MailEngine.getSession();
String storeProtocol = GetterUtil.getString(
session.getProperty("mail.store.protocol"));
if (!storeProtocol.equals(Account.PROTOCOL_POPS)) {
storeProtocol = Account.PROTOCOL_POP;
}
Store store = session.getStore(storeProtocol);
String prefix = "mail." + storeProtocol + ".";
String host = session.getProperty(prefix + "host");
String user = session.getProperty(prefix + "user");
if (Validator.isNull(user)) {
user = session.getProperty("mail.smtp.user");
}
String password = session.getProperty(prefix + "password");
if (Validator.isNull(password)) {
password = session.getProperty("mail.smtp.password");
}
store.connect(host, user, password);
return store;
}
protected void notifyMessageListeners(Message[] messages)
throws MessagingException {
if (_log.isDebugEnabled()) {
_log.debug("Messages " + messages.length);
}
for (Message message : messages) {
if (_log.isDebugEnabled()) {
_log.debug("Message " + message);
}
String from = getEmailAddress(message.getFrom());
String recipient = getEmailAddress(
message.getRecipients(RecipientType.TO));
if (_log.isDebugEnabled()) {
_log.debug("From " + from);
_log.debug("Recipient " + recipient);
}
for (MessageListener messageListener :
_messageListenerWrappers.values()) {
try {
if (messageListener.accept(from, recipient, message)) {
messageListener.deliver(from, recipient, message);
}
}
catch (MessageListenerException mle) {
_log.error(mle, mle);
}
}
}
}
protected void removeMessageListener(MessageListener messageListener) {
_messageListenerWrappers.remove(messageListener);
}
@Reference(target = ModuleServiceLifecycle.PORTAL_INITIALIZED, unbind = "-")
protected void setModuleServiceLifecycle(
ModuleServiceLifecycle moduleServiceLifecycle) {
}
@Reference(unbind = "-")
protected void setSchedulerEngineHelper(
SchedulerEngineHelper schedulerEngineHelper) {
_schedulerEngineHelper = schedulerEngineHelper;
}
@Reference(unbind = "-")
protected void setTriggerFactory(TriggerFactory triggerFactory) {
}
private static final Log _log = LogFactoryUtil.getLog(
POPNotificationsMessageListener.class);
private final Map<MessageListener, MessageListenerWrapper>
_messageListenerWrappers = new ConcurrentHashMap<>();
private SchedulerEngineHelper _schedulerEngineHelper;
@Reference
private TriggerFactory _triggerFactory;
}