001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.messageboards.pop;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.pop.MessageListener;
020    import com.liferay.portal.kernel.pop.MessageListenerException;
021    import com.liferay.portal.kernel.util.CharPool;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.ObjectValuePair;
024    import com.liferay.portal.kernel.util.StreamUtil;
025    import com.liferay.portal.kernel.util.StringUtil;
026    import com.liferay.portal.model.Company;
027    import com.liferay.portal.model.User;
028    import com.liferay.portal.security.auth.PrincipalException;
029    import com.liferay.portal.security.permission.PermissionCheckerUtil;
030    import com.liferay.portal.service.CompanyLocalServiceUtil;
031    import com.liferay.portal.service.ServiceContext;
032    import com.liferay.portal.service.UserLocalServiceUtil;
033    import com.liferay.portal.util.PortalUtil;
034    import com.liferay.portal.util.PortletKeys;
035    import com.liferay.portal.util.PropsValues;
036    import com.liferay.portlet.messageboards.NoSuchCategoryException;
037    import com.liferay.portlet.messageboards.NoSuchMessageException;
038    import com.liferay.portlet.messageboards.model.MBCategory;
039    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
040    import com.liferay.portlet.messageboards.model.MBMessage;
041    import com.liferay.portlet.messageboards.model.MBMessageConstants;
042    import com.liferay.portlet.messageboards.service.MBCategoryLocalServiceUtil;
043    import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
044    import com.liferay.portlet.messageboards.service.MBMessageServiceUtil;
045    import com.liferay.portlet.messageboards.util.MBMailMessage;
046    import com.liferay.portlet.messageboards.util.MBUtil;
047    
048    import java.io.InputStream;
049    
050    import java.util.List;
051    
052    import javax.mail.Message;
053    
054    import org.apache.commons.lang.time.StopWatch;
055    
056    /**
057     * @author Brian Wing Shun Chan
058     * @author Jorge Ferrer
059     * @author Michael C. Han
060     */
061    public class MessageListenerImpl implements MessageListener {
062    
063            public boolean accept(String from, String recipient, Message message) {
064                    try {
065                            String messageId = getMessageId(recipient, message);
066    
067                            if ((messageId == null) ||
068                                    (!messageId.startsWith(
069                                            MBUtil.MESSAGE_POP_PORTLET_PREFIX, getOffset()))) {
070    
071                                    return false;
072                            }
073    
074                            Company company = getCompany(messageId);
075                            long categoryId = getCategoryId(messageId);
076    
077                            MBCategory category = MBCategoryLocalServiceUtil.getCategory(
078                                    categoryId);
079    
080                            if (category.getCompanyId() != company.getCompanyId()) {
081                                    return false;
082                            }
083    
084                            if (_log.isDebugEnabled()) {
085                                    _log.debug("Check to see if user " + from + " exists");
086                            }
087    
088                            UserLocalServiceUtil.getUserByEmailAddress(
089                                    company.getCompanyId(), from);
090    
091                            return true;
092                    }
093                    catch (Exception e) {
094                            if (_log.isErrorEnabled()) {
095                                    _log.error("Unable to process message: " + message, e);
096                            }
097    
098                            return false;
099                    }
100            }
101    
102            public void deliver(String from, String recipient, Message message)
103                    throws MessageListenerException {
104    
105                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs = null;
106    
107                    try {
108                            StopWatch stopWatch = null;
109    
110                            if (_log.isDebugEnabled()) {
111                                    stopWatch = new StopWatch();
112    
113                                    stopWatch.start();
114    
115                                    _log.debug("Deliver message from " + from + " to " + recipient);
116                            }
117    
118                            String messageId = getMessageId(recipient, message);
119    
120                            Company company = getCompany(messageId);
121    
122                            if (_log.isDebugEnabled()) {
123                                    _log.debug("Message id " + messageId);
124                            }
125    
126                            long groupId = 0;
127                            long categoryId = getCategoryId(messageId);
128    
129                            try {
130                                    MBCategory category = MBCategoryLocalServiceUtil.getCategory(
131                                            categoryId);
132    
133                                    groupId = category.getGroupId();
134                            }
135                            catch (NoSuchCategoryException nsce) {
136                                    groupId = categoryId;
137                                    categoryId = MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
138                            }
139    
140                            if (_log.isDebugEnabled()) {
141                                    _log.debug("Group id " + groupId);
142                                    _log.debug("Category id " + categoryId);
143                            }
144    
145                            User user = UserLocalServiceUtil.getUserByEmailAddress(
146                                    company.getCompanyId(), from);
147    
148                            long parentMessageId = getParentMessageId(recipient, message);
149    
150                            if (_log.isDebugEnabled()) {
151                                    _log.debug("Parent message id " + parentMessageId);
152                            }
153    
154                            MBMessage parentMessage = null;
155    
156                            try {
157                                    if (parentMessageId > 0) {
158                                            parentMessage = MBMessageLocalServiceUtil.getMessage(
159                                                    parentMessageId);
160                                    }
161                            }
162                            catch (NoSuchMessageException nsme) {
163    
164                                    // If the parent message does not exist we ignore it and post
165                                    // the message as a new thread.
166    
167                            }
168    
169                            if (_log.isDebugEnabled()) {
170                                    _log.debug("Parent message " + parentMessage);
171                            }
172    
173                            String subject = MBUtil.getSubjectWithoutMessageId(message);
174    
175                            MBMailMessage mbMailMessage = new MBMailMessage();
176    
177                            MBUtil.collectPartContent(message, mbMailMessage);
178    
179                            inputStreamOVPs = mbMailMessage.getInputStreamOVPs();
180    
181                            PermissionCheckerUtil.setThreadValues(user);
182    
183                            ServiceContext serviceContext = new ServiceContext();
184    
185                            serviceContext.setAddGroupPermissions(true);
186                            serviceContext.setAddGuestPermissions(true);
187                            serviceContext.setLayoutFullURL(
188                                    PortalUtil.getLayoutFullURL(
189                                            groupId, PortletKeys.MESSAGE_BOARDS));
190                            serviceContext.setScopeGroupId(groupId);
191    
192                            if (parentMessage == null) {
193                                    MBMessageServiceUtil.addMessage(
194                                            groupId, categoryId, subject, mbMailMessage.getBody(),
195                                            MBMessageConstants.DEFAULT_FORMAT, inputStreamOVPs, false,
196                                            0.0, true, serviceContext);
197                            }
198                            else {
199                                    MBMessageServiceUtil.addMessage(
200                                            groupId, categoryId, parentMessage.getThreadId(),
201                                            parentMessage.getMessageId(), subject,
202                                            mbMailMessage.getBody(), MBMessageConstants.DEFAULT_FORMAT,
203                                            inputStreamOVPs, false, 0.0, true, serviceContext);
204                            }
205    
206                            if (_log.isDebugEnabled()) {
207                                    _log.debug(
208                                            "Delivering message takes " + stopWatch.getTime() + " ms");
209                            }
210                    }
211                    catch (PrincipalException pe) {
212                            if (_log.isDebugEnabled()) {
213                                    _log.debug("Prevented unauthorized post from " + from);
214                            }
215    
216                            throw new MessageListenerException(pe);
217                    }
218                    catch (Exception e) {
219                            _log.error(e, e);
220    
221                            throw new MessageListenerException(e);
222                    }
223                    finally {
224                            if (inputStreamOVPs != null) {
225                                    for (ObjectValuePair<String, InputStream> inputStreamOVP :
226                                                    inputStreamOVPs) {
227    
228                                            InputStream inputStream = inputStreamOVP.getValue();
229    
230                                            StreamUtil.cleanUp(inputStream);
231                                    }
232                            }
233    
234                            PermissionCheckerUtil.setThreadValues(null);
235                    }
236            }
237    
238            public String getId() {
239                    return MessageListenerImpl.class.getName();
240            }
241    
242            protected long getCategoryId(String recipient) {
243                    int pos = recipient.indexOf(CharPool.AT);
244    
245                    String target = recipient.substring(
246                            MBUtil.MESSAGE_POP_PORTLET_PREFIX.length() + getOffset(), pos);
247    
248                    String[] parts = StringUtil.split(target, CharPool.PERIOD);
249    
250                    return GetterUtil.getLong(parts[0]);
251            }
252    
253            protected Company getCompany(String messageId) throws Exception {
254                    int pos =
255                            messageId.indexOf(CharPool.AT) +
256                                    PropsValues.POP_SERVER_SUBDOMAIN.length() + 1;
257    
258                    if (PropsValues.POP_SERVER_SUBDOMAIN.length() > 0) {
259                            pos++;
260                    }
261    
262                    int endPos = messageId.indexOf(CharPool.GREATER_THAN, pos);
263    
264                    if (endPos == -1) {
265                            endPos = messageId.length();
266                    }
267    
268                    String mx = messageId.substring(pos, endPos);
269    
270                    return CompanyLocalServiceUtil.getCompanyByMx(mx);
271            }
272    
273            protected String getMessageId(String recipient, Message message)
274                    throws Exception {
275    
276                    if (PropsValues.POP_SERVER_SUBDOMAIN.length() > 0) {
277                            return recipient;
278                    }
279                    else {
280                            return MBUtil.getParentMessageIdString(message);
281                    }
282            }
283    
284            protected int getOffset() {
285                    if (PropsValues.POP_SERVER_SUBDOMAIN.length() == 0) {
286                            return 1;
287                    }
288    
289                    return 0;
290            }
291    
292            protected long getParentMessageId(String recipient, Message message)
293                    throws Exception {
294    
295                    if (!StringUtil.startsWith(
296                                    recipient, MBUtil.MESSAGE_POP_PORTLET_PREFIX)) {
297    
298                            return MBUtil.getParentMessageId(message);
299                    }
300    
301                    int pos = recipient.indexOf(CharPool.AT);
302    
303                    if (pos < 0) {
304                            return MBUtil.getParentMessageId(message);
305                    }
306    
307                    String target = recipient.substring(
308                            MBUtil.MESSAGE_POP_PORTLET_PREFIX.length(), pos);
309    
310                    String[] parts = StringUtil.split(target, CharPool.PERIOD);
311    
312                    long parentMessageId = 0;
313    
314                    if (parts.length == 2) {
315                            parentMessageId = GetterUtil.getLong(parts[1]);
316                    }
317    
318                    if (parentMessageId > 0) {
319                            return parentMessageId;
320                    }
321    
322                    return MBUtil.getParentMessageId(message);
323            }
324    
325            private static Log _log = LogFactoryUtil.getLog(MessageListenerImpl.class);
326    
327    }