001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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                            if (from.equalsIgnoreCase(
089                                            PropsValues.MAIL_SESSION_MAIL_POP3_USER)) {
090    
091                                    return false;
092                            }
093    
094                            UserLocalServiceUtil.getUserByEmailAddress(
095                                    company.getCompanyId(), from);
096    
097                            return true;
098                    }
099                    catch (Exception e) {
100                            if (_log.isErrorEnabled()) {
101                                    _log.error("Unable to process message: " + message, e);
102                            }
103    
104                            return false;
105                    }
106            }
107    
108            public void deliver(String from, String recipient, Message message)
109                    throws MessageListenerException {
110    
111                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs = null;
112    
113                    try {
114                            StopWatch stopWatch = null;
115    
116                            if (_log.isDebugEnabled()) {
117                                    stopWatch = new StopWatch();
118    
119                                    stopWatch.start();
120    
121                                    _log.debug("Deliver message from " + from + " to " + recipient);
122                            }
123    
124                            String messageId = getMessageId(recipient, message);
125    
126                            Company company = getCompany(messageId);
127    
128                            if (_log.isDebugEnabled()) {
129                                    _log.debug("Message id " + messageId);
130                            }
131    
132                            long groupId = 0;
133                            long categoryId = getCategoryId(messageId);
134    
135                            try {
136                                    MBCategory category = MBCategoryLocalServiceUtil.getCategory(
137                                            categoryId);
138    
139                                    groupId = category.getGroupId();
140                            }
141                            catch (NoSuchCategoryException nsce) {
142                                    groupId = categoryId;
143                                    categoryId = MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
144                            }
145    
146                            if (_log.isDebugEnabled()) {
147                                    _log.debug("Group id " + groupId);
148                                    _log.debug("Category id " + categoryId);
149                            }
150    
151                            User user = UserLocalServiceUtil.getUserByEmailAddress(
152                                    company.getCompanyId(), from);
153    
154                            long parentMessageId = getParentMessageId(recipient, message);
155    
156                            if (_log.isDebugEnabled()) {
157                                    _log.debug("Parent message id " + parentMessageId);
158                            }
159    
160                            MBMessage parentMessage = null;
161    
162                            try {
163                                    if (parentMessageId > 0) {
164                                            parentMessage = MBMessageLocalServiceUtil.getMessage(
165                                                    parentMessageId);
166                                    }
167                            }
168                            catch (NoSuchMessageException nsme) {
169    
170                                    // If the parent message does not exist we ignore it and post
171                                    // the message as a new thread.
172    
173                            }
174    
175                            if (_log.isDebugEnabled()) {
176                                    _log.debug("Parent message " + parentMessage);
177                            }
178    
179                            String subject = MBUtil.getSubjectWithoutMessageId(message);
180    
181                            MBMailMessage mbMailMessage = new MBMailMessage();
182    
183                            MBUtil.collectPartContent(message, mbMailMessage);
184    
185                            inputStreamOVPs = mbMailMessage.getInputStreamOVPs();
186    
187                            PermissionCheckerUtil.setThreadValues(user);
188    
189                            ServiceContext serviceContext = new ServiceContext();
190    
191                            serviceContext.setAddGroupPermissions(true);
192                            serviceContext.setAddGuestPermissions(true);
193                            serviceContext.setLayoutFullURL(
194                                    PortalUtil.getLayoutFullURL(
195                                            groupId, PortletKeys.MESSAGE_BOARDS));
196                            serviceContext.setScopeGroupId(groupId);
197    
198                            if (parentMessage == null) {
199                                    MBMessageServiceUtil.addMessage(
200                                            groupId, categoryId, subject, mbMailMessage.getBody(),
201                                            MBMessageConstants.DEFAULT_FORMAT, inputStreamOVPs, false,
202                                            0.0, true, serviceContext);
203                            }
204                            else {
205                                    MBMessageServiceUtil.addMessage(
206                                            groupId, categoryId, parentMessage.getThreadId(),
207                                            parentMessage.getMessageId(), subject,
208                                            mbMailMessage.getBody(), MBMessageConstants.DEFAULT_FORMAT,
209                                            inputStreamOVPs, false, 0.0, true, serviceContext);
210                            }
211    
212                            if (_log.isDebugEnabled()) {
213                                    _log.debug(
214                                            "Delivering message takes " + stopWatch.getTime() + " ms");
215                            }
216                    }
217                    catch (PrincipalException pe) {
218                            if (_log.isDebugEnabled()) {
219                                    _log.debug("Prevented unauthorized post from " + from);
220                            }
221    
222                            throw new MessageListenerException(pe);
223                    }
224                    catch (Exception e) {
225                            _log.error(e, e);
226    
227                            throw new MessageListenerException(e);
228                    }
229                    finally {
230                            if (inputStreamOVPs != null) {
231                                    for (ObjectValuePair<String, InputStream> inputStreamOVP :
232                                                    inputStreamOVPs) {
233    
234                                            InputStream inputStream = inputStreamOVP.getValue();
235    
236                                            StreamUtil.cleanUp(inputStream);
237                                    }
238                            }
239    
240                            PermissionCheckerUtil.setThreadValues(null);
241                    }
242            }
243    
244            public String getId() {
245                    return MessageListenerImpl.class.getName();
246            }
247    
248            protected long getCategoryId(String recipient) {
249                    int pos = recipient.indexOf(CharPool.AT);
250    
251                    String target = recipient.substring(
252                            MBUtil.MESSAGE_POP_PORTLET_PREFIX.length() + getOffset(), pos);
253    
254                    String[] parts = StringUtil.split(target, CharPool.PERIOD);
255    
256                    return GetterUtil.getLong(parts[0]);
257            }
258    
259            protected Company getCompany(String messageId) throws Exception {
260                    int pos =
261                            messageId.indexOf(CharPool.AT) +
262                                    PropsValues.POP_SERVER_SUBDOMAIN.length() + 1;
263    
264                    if (PropsValues.POP_SERVER_SUBDOMAIN.length() > 0) {
265                            pos++;
266                    }
267    
268                    int endPos = messageId.indexOf(CharPool.GREATER_THAN, pos);
269    
270                    if (endPos == -1) {
271                            endPos = messageId.length();
272                    }
273    
274                    String mx = messageId.substring(pos, endPos);
275    
276                    return CompanyLocalServiceUtil.getCompanyByMx(mx);
277            }
278    
279            protected String getMessageId(String recipient, Message message)
280                    throws Exception {
281    
282                    if (PropsValues.POP_SERVER_SUBDOMAIN.length() > 0) {
283                            return recipient;
284                    }
285                    else {
286                            return MBUtil.getParentMessageIdString(message);
287                    }
288            }
289    
290            protected int getOffset() {
291                    if (PropsValues.POP_SERVER_SUBDOMAIN.length() == 0) {
292                            return 1;
293                    }
294    
295                    return 0;
296            }
297    
298            protected long getParentMessageId(String recipient, Message message)
299                    throws Exception {
300    
301                    if (!StringUtil.startsWith(
302                                    recipient, MBUtil.MESSAGE_POP_PORTLET_PREFIX)) {
303    
304                            return MBUtil.getParentMessageId(message);
305                    }
306    
307                    int pos = recipient.indexOf(CharPool.AT);
308    
309                    if (pos < 0) {
310                            return MBUtil.getParentMessageId(message);
311                    }
312    
313                    String target = recipient.substring(
314                            MBUtil.MESSAGE_POP_PORTLET_PREFIX.length(), pos);
315    
316                    String[] parts = StringUtil.split(target, CharPool.PERIOD);
317    
318                    long parentMessageId = 0;
319    
320                    if (parts.length == 2) {
321                            parentMessageId = GetterUtil.getLong(parts[1]);
322                    }
323    
324                    if (parentMessageId > 0) {
325                            return parentMessageId;
326                    }
327    
328                    return MBUtil.getParentMessageId(message);
329            }
330    
331            private static Log _log = LogFactoryUtil.getLog(MessageListenerImpl.class);
332    
333    }