1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.blogs.service.impl;
16  
17  import com.liferay.portal.NoSuchUserException;
18  import com.liferay.portal.kernel.exception.PortalException;
19  import com.liferay.portal.kernel.exception.SystemException;
20  import com.liferay.portal.kernel.log.Log;
21  import com.liferay.portal.kernel.log.LogFactoryUtil;
22  import com.liferay.portal.kernel.messaging.DestinationNames;
23  import com.liferay.portal.kernel.messaging.Message;
24  import com.liferay.portal.kernel.messaging.MessageBusUtil;
25  import com.liferay.portal.kernel.search.Indexer;
26  import com.liferay.portal.kernel.search.IndexerRegistryUtil;
27  import com.liferay.portal.kernel.util.ContentTypes;
28  import com.liferay.portal.kernel.util.HtmlUtil;
29  import com.liferay.portal.kernel.util.HttpUtil;
30  import com.liferay.portal.kernel.util.LocaleUtil;
31  import com.liferay.portal.kernel.util.OrderByComparator;
32  import com.liferay.portal.kernel.util.SetUtil;
33  import com.liferay.portal.kernel.util.StringBundler;
34  import com.liferay.portal.kernel.util.StringPool;
35  import com.liferay.portal.kernel.util.StringUtil;
36  import com.liferay.portal.kernel.util.Validator;
37  import com.liferay.portal.kernel.workflow.StatusConstants;
38  import com.liferay.portal.model.Company;
39  import com.liferay.portal.model.Group;
40  import com.liferay.portal.model.ResourceConstants;
41  import com.liferay.portal.model.User;
42  import com.liferay.portal.service.ServiceContext;
43  import com.liferay.portal.service.ServiceContextUtil;
44  import com.liferay.portal.util.Portal;
45  import com.liferay.portal.util.PortalUtil;
46  import com.liferay.portal.util.PortletKeys;
47  import com.liferay.portal.util.PropsValues;
48  import com.liferay.portlet.blogs.EntryContentException;
49  import com.liferay.portlet.blogs.EntryDisplayDateException;
50  import com.liferay.portlet.blogs.EntryTitleException;
51  import com.liferay.portlet.blogs.model.BlogsEntry;
52  import com.liferay.portlet.blogs.service.base.BlogsEntryLocalServiceBaseImpl;
53  import com.liferay.portlet.blogs.social.BlogsActivityKeys;
54  import com.liferay.portlet.blogs.util.BlogsUtil;
55  import com.liferay.portlet.blogs.util.LinkbackProducerUtil;
56  import com.liferay.portlet.blogs.util.comparator.EntryDisplayDateComparator;
57  
58  import java.io.IOException;
59  
60  import java.util.Date;
61  import java.util.HashMap;
62  import java.util.HashSet;
63  import java.util.List;
64  import java.util.Map;
65  import java.util.Set;
66  
67  import javax.portlet.PortletPreferences;
68  
69  import net.htmlparser.jericho.Source;
70  import net.htmlparser.jericho.StartTag;
71  
72  /**
73   * <a href="BlogsEntryLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
74   *
75   * @author Brian Wing Shun Chan
76   * @author Wilson S. Man
77   * @author Raymond Augé
78   * @author Thiago Moreira
79   */
80  public class BlogsEntryLocalServiceImpl extends BlogsEntryLocalServiceBaseImpl {
81  
82      public BlogsEntry addEntry(
83              String uuid, long userId, String title, String content,
84              int displayDateMonth, int displayDateDay, int displayDateYear,
85              int displayDateHour, int displayDateMinute, boolean allowPingbacks,
86              boolean allowTrackbacks, String[] trackbacks,
87              ServiceContext serviceContext)
88          throws PortalException, SystemException {
89  
90          // Entry
91  
92          User user = userPersistence.findByPrimaryKey(userId);
93          long groupId = serviceContext.getScopeGroupId();
94  
95          Date displayDate = PortalUtil.getDate(
96              displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
97              displayDateMinute, user.getTimeZone(),
98              new EntryDisplayDateException());
99  
100         Date now = new Date();
101 
102         validate(title, content);
103 
104         long entryId = counterLocalService.increment();
105 
106         BlogsEntry entry = blogsEntryPersistence.create(entryId);
107 
108         entry.setUuid(uuid);
109         entry.setGroupId(groupId);
110         entry.setCompanyId(user.getCompanyId());
111         entry.setUserId(user.getUserId());
112         entry.setUserName(user.getFullName());
113         entry.setCreateDate(now);
114         entry.setModifiedDate(now);
115         entry.setTitle(title);
116         entry.setUrlTitle(getUniqueUrlTitle(entryId, groupId, title));
117         entry.setContent(content);
118         entry.setDisplayDate(displayDate);
119         entry.setAllowPingbacks(allowPingbacks);
120         entry.setAllowTrackbacks(allowTrackbacks);
121         entry.setStatus(serviceContext.getStatus());
122         entry.setStatusByUserId(user.getUserId());
123         entry.setStatusByUserName(user.getFullName());
124         entry.setStatusDate(now);
125         entry.setExpandoBridgeAttributes(serviceContext);
126 
127         blogsEntryPersistence.update(entry, false);
128 
129         // Resources
130 
131         if (serviceContext.getAddCommunityPermissions() ||
132             serviceContext.getAddGuestPermissions()) {
133 
134             addEntryResources(
135                 entry, serviceContext.getAddCommunityPermissions(),
136                 serviceContext.getAddGuestPermissions());
137         }
138         else {
139             addEntryResources(
140                 entry, serviceContext.getCommunityPermissions(),
141                 serviceContext.getGuestPermissions());
142         }
143 
144         // Asset
145 
146         updateAsset(
147             userId, entry, serviceContext.getAssetCategoryIds(),
148             serviceContext.getAssetTagNames());
149 
150         // Message boards
151 
152         if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
153             mbMessageLocalService.addDiscussionMessage(
154                 userId, entry.getUserName(), BlogsEntry.class.getName(),
155                 entryId, StatusConstants.APPROVED);
156         }
157 
158         // Status
159 
160         entry = updateWorkflowStatus(
161             userId, entryId, trackbacks, false, serviceContext);
162 
163         return entry;
164     }
165 
166     public void addEntryResources(
167             BlogsEntry entry, boolean addCommunityPermissions,
168             boolean addGuestPermissions)
169         throws PortalException, SystemException {
170 
171         resourceLocalService.addResources(
172             entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
173             BlogsEntry.class.getName(), entry.getEntryId(), false,
174             addCommunityPermissions, addGuestPermissions);
175     }
176 
177     public void addEntryResources(
178             BlogsEntry entry, String[] communityPermissions,
179             String[] guestPermissions)
180         throws PortalException, SystemException {
181 
182         resourceLocalService.addModelResources(
183             entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
184             BlogsEntry.class.getName(), entry.getEntryId(),
185             communityPermissions, guestPermissions);
186     }
187 
188     public void addEntryResources(
189             long entryId, boolean addCommunityPermissions,
190             boolean addGuestPermissions)
191         throws PortalException, SystemException {
192 
193         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
194 
195         addEntryResources(entry, addCommunityPermissions, addGuestPermissions);
196     }
197 
198     public void addEntryResources(
199             long entryId, String[] communityPermissions,
200             String[] guestPermissions)
201         throws PortalException, SystemException {
202 
203         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
204 
205         addEntryResources(entry, communityPermissions, guestPermissions);
206     }
207 
208     public void deleteEntries(long groupId)
209         throws PortalException, SystemException {
210 
211         for (BlogsEntry entry : blogsEntryPersistence.findByGroupId(groupId)) {
212             deleteEntry(entry);
213         }
214     }
215 
216     public void deleteEntry(BlogsEntry entry)
217         throws PortalException, SystemException {
218 
219         // Entry
220 
221         blogsEntryPersistence.remove(entry);
222 
223         // Resources
224 
225         resourceLocalService.deleteResource(
226             entry.getCompanyId(), BlogsEntry.class.getName(),
227             ResourceConstants.SCOPE_INDIVIDUAL, entry.getEntryId());
228 
229         // Statistics
230 
231         blogsStatsUserLocalService.updateStatsUser(
232             entry.getGroupId(), entry.getUserId());
233 
234         // Asset
235 
236         assetEntryLocalService.deleteEntry(
237             BlogsEntry.class.getName(), entry.getEntryId());
238 
239         // Expando
240 
241         expandoValueLocalService.deleteValues(
242             BlogsEntry.class.getName(), entry.getEntryId());
243 
244         // Message boards
245 
246         mbMessageLocalService.deleteDiscussionMessages(
247             BlogsEntry.class.getName(), entry.getEntryId());
248 
249         // Ratings
250 
251         ratingsStatsLocalService.deleteStats(
252             BlogsEntry.class.getName(), entry.getEntryId());
253 
254         // Social
255 
256         socialActivityLocalService.deleteActivities(
257             BlogsEntry.class.getName(), entry.getEntryId());
258 
259         // Indexer
260 
261         Indexer indexer = IndexerRegistryUtil.getIndexer(BlogsEntry.class);
262 
263         indexer.delete(entry);
264     }
265 
266     public void deleteEntry(long entryId)
267         throws PortalException, SystemException {
268 
269         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
270 
271         deleteEntry(entry);
272     }
273 
274     public List<BlogsEntry> getCompanyEntries(
275             long companyId, int status, int start, int end)
276         throws SystemException {
277 
278         if (status == StatusConstants.ANY) {
279             return blogsEntryPersistence.findByC_D(
280                 companyId, new Date(), start, end);
281         }
282         else {
283             return blogsEntryPersistence.findByC_D_S(
284                 companyId, new Date(), status, start, end);
285         }
286     }
287 
288     public List<BlogsEntry> getCompanyEntries(
289             long companyId, int status, int start, int end,
290             OrderByComparator obc)
291         throws SystemException {
292 
293         if (status == StatusConstants.ANY) {
294             return blogsEntryPersistence.findByC_D(
295                 companyId, new Date(), start, end, obc);
296         }
297         else {
298             return blogsEntryPersistence.findByC_D_S(
299                 companyId, new Date(), status, start, end, obc);
300         }
301     }
302 
303     public int getCompanyEntriesCount(long companyId, int status)
304         throws SystemException {
305 
306         if (status == StatusConstants.ANY) {
307             return blogsEntryPersistence.countByC_D(
308                 companyId, new Date());
309         }
310         else {
311             return blogsEntryPersistence.countByC_D_S(
312                 companyId, new Date(), status);
313         }
314     }
315 
316     public BlogsEntry[] getEntriesPrevAndNext(long entryId)
317         throws PortalException, SystemException {
318 
319         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
320 
321         return blogsEntryPersistence.findByGroupId_PrevAndNext(
322             entry.getEntryId(), entry.getGroupId(),
323             new EntryDisplayDateComparator(true));
324     }
325 
326     public BlogsEntry getEntry(long entryId)
327         throws PortalException, SystemException {
328 
329         return blogsEntryPersistence.findByPrimaryKey(entryId);
330     }
331 
332     public BlogsEntry getEntry(long groupId, String urlTitle)
333         throws PortalException, SystemException {
334 
335         return blogsEntryPersistence.findByG_UT(groupId, urlTitle);
336     }
337 
338     public List<BlogsEntry> getGroupEntries(
339             long groupId, int status, int start, int end)
340         throws SystemException {
341 
342         if (status == StatusConstants.ANY) {
343             return blogsEntryPersistence.findByG_D(
344                 groupId, new Date(), start, end);
345         }
346         else {
347             return blogsEntryPersistence.findByG_D_S(
348                 groupId, new Date(), status, start, end);
349         }
350     }
351 
352     public List<BlogsEntry> getGroupEntries(
353             long groupId, int status, int start, int end, OrderByComparator obc)
354         throws SystemException {
355 
356         if (status == StatusConstants.ANY) {
357             return blogsEntryPersistence.findByG_D(
358                 groupId, new Date(), start, end, obc);
359         }
360         else {
361             return blogsEntryPersistence.findByG_D_S(
362                 groupId, new Date(), status, start, end, obc);
363         }
364     }
365 
366     public int getGroupEntriesCount(long groupId, int status)
367         throws SystemException {
368 
369         if (status == StatusConstants.ANY) {
370             return blogsEntryPersistence.countByG_D(groupId, new Date());
371         }
372         else {
373             return blogsEntryPersistence.countByG_D_S(
374                 groupId, new Date(), status);
375         }
376     }
377 
378     public List<BlogsEntry> getGroupUserEntries(
379             long groupId, long userId, int status, int start, int end)
380         throws SystemException {
381 
382         if (status == StatusConstants.ANY) {
383             return blogsEntryPersistence.findByG_U_D(
384                 groupId, userId, new Date(), start, end);
385         }
386         else {
387             return blogsEntryPersistence.findByG_U_D_S(
388                 groupId, userId, new Date(), status, start, end);
389         }
390     }
391 
392     public List<BlogsEntry> getGroupUserEntries(
393             long groupId, long userId, int status, int start, int end,
394             OrderByComparator obc)
395         throws SystemException {
396 
397         if (status == StatusConstants.ANY) {
398             return blogsEntryPersistence.findByG_U_D(
399                 groupId, userId, new Date(), start, end, obc);
400         }
401         else {
402             return blogsEntryPersistence.findByG_U_D_S(
403                 groupId, userId, new Date(), status, start, end, obc);
404         }
405     }
406 
407     public int getGroupUserEntriesCount(long groupId, long userId, int status)
408         throws SystemException {
409 
410         if (status == StatusConstants.ANY) {
411             return blogsEntryPersistence.countByG_U_D(
412                 groupId, userId, new Date());
413         }
414         else {
415             return blogsEntryPersistence.countByG_U_D_S(
416                 groupId, userId, new Date(), status);
417         }
418     }
419 
420     public List<BlogsEntry> getNoAssetEntries() throws SystemException {
421         return blogsEntryFinder.findByNoAssets();
422     }
423 
424     public List<BlogsEntry> getOrganizationEntries(
425             long organizationId, int status, int start, int end)
426         throws SystemException {
427 
428         return blogsEntryFinder.findByOrganizationId(
429             organizationId, new Date(), status, start, end);
430     }
431 
432     public int getOrganizationEntriesCount(long organizationId, int status)
433         throws SystemException {
434 
435         return blogsEntryFinder.countByOrganizationId(
436             organizationId, new Date(), status);
437     }
438 
439     public void updateAsset(
440             long userId, BlogsEntry entry, long[] assetCategoryIds,
441             String[] assetTagNames)
442         throws PortalException, SystemException {
443 
444         boolean visible = false;
445 
446         if (entry.getStatus() == StatusConstants.APPROVED) {
447             visible = true;
448         }
449 
450         assetEntryLocalService.updateEntry(
451             userId, entry.getGroupId(), BlogsEntry.class.getName(),
452             entry.getEntryId(), assetCategoryIds, assetTagNames, visible, null,
453             null, entry.getDisplayDate(), null, ContentTypes.TEXT_HTML,
454             entry.getTitle(), null, null, null, 0, 0, null, false);
455     }
456 
457     public BlogsEntry updateEntry(
458             long userId, long entryId, String title, String content,
459             int displayDateMonth, int displayDateDay, int displayDateYear,
460             int displayDateHour, int displayDateMinute, boolean allowPingbacks,
461             boolean allowTrackbacks, String[] trackbacks,
462             ServiceContext serviceContext)
463         throws PortalException, SystemException {
464 
465         // Entry
466 
467         User user = userPersistence.findByPrimaryKey(userId);
468 
469         Date displayDate = PortalUtil.getDate(
470             displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
471             displayDateMinute, user.getTimeZone(),
472             new EntryDisplayDateException());
473 
474         validate(title, content);
475 
476         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
477 
478         String oldUrlTitle = entry.getUrlTitle();
479 
480         entry.setModifiedDate(new Date());
481         entry.setTitle(title);
482         entry.setUrlTitle(
483             getUniqueUrlTitle(entryId, entry.getGroupId(), title));
484         entry.setContent(content);
485         entry.setDisplayDate(displayDate);
486         entry.setAllowPingbacks(allowPingbacks);
487         entry.setAllowTrackbacks(allowTrackbacks);
488         entry.setExpandoBridgeAttributes(serviceContext);
489 
490         blogsEntryPersistence.update(entry, false);
491 
492         // Resources
493 
494         if ((serviceContext.getCommunityPermissions() != null) ||
495             (serviceContext.getGuestPermissions() != null)) {
496 
497             updateEntryResources(
498                 entry, serviceContext.getCommunityPermissions(),
499                 serviceContext.getGuestPermissions());
500         }
501 
502         // Asset
503 
504         updateAsset(
505             userId, entry, serviceContext.getAssetCategoryIds(),
506             serviceContext.getAssetTagNames());
507 
508         // Status
509 
510         boolean pingOldTrackbacks = false;
511 
512         if (!oldUrlTitle.equals(entry.getUrlTitle())) {
513             pingOldTrackbacks = true;
514         }
515 
516         entry = updateWorkflowStatus(
517             userId, entryId, trackbacks, pingOldTrackbacks, serviceContext);
518 
519         return entry;
520     }
521 
522     public void updateEntryResources(
523             BlogsEntry entry, String[] communityPermissions,
524             String[] guestPermissions)
525         throws PortalException, SystemException {
526 
527         resourceLocalService.updateResources(
528             entry.getCompanyId(), entry.getGroupId(),
529             BlogsEntry.class.getName(), entry.getEntryId(),
530             communityPermissions, guestPermissions);
531     }
532 
533     public BlogsEntry updateWorkflowStatus(
534             long userId, long entryId, String[] trackbacks,
535             boolean pingOldTrackbaks, ServiceContext serviceContext)
536         throws PortalException, SystemException {
537 
538         // Entry
539 
540         User user = userPersistence.findByPrimaryKey(userId);
541         Date now = new Date();
542 
543         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
544 
545         entry.setModifiedDate(now);
546         entry.setStatus(serviceContext.getStatus());
547         entry.setStatusByUserId(user.getUserId());
548         entry.setStatusByUserName(user.getFullName());
549         entry.setStatusDate(now);
550 
551         blogsEntryPersistence.update(entry, false);
552 
553         // Statistics
554 
555         if (entry.isApproved()) {
556             blogsStatsUserLocalService.updateStatsUser(
557                 entry.getGroupId(), entry.getUserId(), entry.getDisplayDate());
558         }
559 
560         // Asset
561 
562         if (entry.isApproved()) {
563             assetEntryLocalService.updateVisible(
564                 BlogsEntry.class.getName(), entryId, true);
565         }
566         else {
567             assetEntryLocalService.updateVisible(
568                 BlogsEntry.class.getName(), entryId, false);
569         }
570 
571         // Social
572 
573         if (entry.isApproved()) {
574             socialActivityLocalService.addUniqueActivity(
575                 entry.getUserId(), entry.getGroupId(),
576                 BlogsEntry.class.getName(), entryId,
577                 BlogsActivityKeys.ADD_ENTRY, StringPool.BLANK, 0);
578         }
579 
580         // Indexer
581 
582         Indexer indexer = IndexerRegistryUtil.getIndexer(BlogsEntry.class);
583 
584         if (entry.isApproved()) {
585             indexer.reindex(entry);
586         }
587         else {
588             indexer.delete(entry);
589         }
590 
591         // Subscriptions
592 
593         notifySubscribers(entry, serviceContext);
594 
595         // Ping
596 
597         pingGoogle(entry, serviceContext);
598         pingPingback(entry, serviceContext);
599         pingTrackbacks(entry, trackbacks, pingOldTrackbaks, serviceContext);
600 
601         return entry;
602     }
603 
604     protected String getUniqueUrlTitle(
605             long entryId, long groupId, String title)
606         throws SystemException {
607 
608         String urlTitle = BlogsUtil.getUrlTitle(entryId, title);
609 
610         String newUrlTitle = urlTitle;
611 
612         for (int i = 1;; i++) {
613             BlogsEntry entry = blogsEntryPersistence.fetchByG_UT(
614                 groupId, newUrlTitle);
615 
616             if ((entry == null) || (entry.getEntryId() == entryId)) {
617                 break;
618             }
619             else {
620                 newUrlTitle = urlTitle + StringPool.DASH + i;
621             }
622         }
623 
624         return newUrlTitle;
625     }
626 
627     protected void notifySubscribers(
628             BlogsEntry entry, ServiceContext serviceContext)
629         throws PortalException, SystemException {
630 
631         if (!entry.isApproved()) {
632             return;
633         }
634 
635         String layoutFullURL = PortalUtil.getLayoutFullURL(
636             serviceContext.getScopeGroupId(), PortletKeys.BLOGS);
637 
638         if (Validator.isNull(layoutFullURL)) {
639             return;
640         }
641 
642         PortletPreferences preferences =
643             ServiceContextUtil.getPortletPreferences(serviceContext);
644 
645         if (preferences == null) {
646             long ownerId = entry.getGroupId();
647             int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
648             long plid = PortletKeys.PREFS_PLID_SHARED;
649             String portletId = PortletKeys.BLOGS;
650             String defaultPreferences = null;
651 
652             preferences = portletPreferencesLocalService.getPreferences(
653                 entry.getCompanyId(), ownerId, ownerType, plid, portletId,
654                 defaultPreferences);
655         }
656 
657         if (serviceContext.isCommandAdd() &&
658             BlogsUtil.getEmailEntryAddedEnabled(preferences)) {
659         }
660         else if (serviceContext.isCommandUpdate() &&
661                  BlogsUtil.getEmailEntryUpdatedEnabled(preferences)) {
662         }
663         else {
664             return;
665         }
666 
667         Company company = companyPersistence.findByPrimaryKey(
668             entry.getCompanyId());
669 
670         Group group = groupPersistence.findByPrimaryKey(
671             serviceContext.getScopeGroupId());
672 
673         String emailAddress = StringPool.BLANK;
674         String fullName = entry.getUserName();
675 
676         try {
677             User user = userPersistence.findByPrimaryKey(entry.getUserId());
678 
679             emailAddress = user.getEmailAddress();
680             fullName = user.getFullName();
681         }
682         catch (NoSuchUserException nsue) {
683         }
684 
685         String portletName = PortalUtil.getPortletTitle(
686             PortletKeys.BLOGS, LocaleUtil.getDefault());
687 
688         String fromName = BlogsUtil.getEmailFromName(preferences);
689         String fromAddress = BlogsUtil.getEmailFromAddress(preferences);
690 
691         fromName = StringUtil.replace(
692             fromName,
693             new String[] {
694                 "[$BLOGS_ENTRY_USER_ADDRESS$]",
695                 "[$BLOGS_ENTRY_USER_NAME$]",
696                 "[$COMPANY_ID$]",
697                 "[$COMPANY_MX$]",
698                 "[$COMPANY_NAME$]",
699                 "[$COMMUNITY_NAME$]",
700                 "[$PORTLET_NAME$]"
701             },
702             new String[] {
703                 emailAddress,
704                 fullName,
705                 String.valueOf(company.getCompanyId()),
706                 company.getMx(),
707                 company.getName(),
708                 group.getName(),
709                 portletName
710             });
711 
712         fromAddress = StringUtil.replace(
713             fromAddress,
714             new String[] {
715                 "[$BLOGS_ENTRY_USER_ADDRESS$]",
716                 "[$BLOGS_ENTRY_USER_NAME$]",
717                 "[$COMPANY_ID$]",
718                 "[$COMPANY_MX$]",
719                 "[$COMPANY_NAME$]",
720                 "[$COMMUNITY_NAME$]",
721                 "[$PORTLET_NAME$]"
722             },
723             new String[] {
724                 emailAddress,
725                 fullName,
726                 String.valueOf(company.getCompanyId()),
727                 company.getMx(),
728                 company.getName(),
729                 group.getName(),
730                 portletName
731             });
732 
733         String entryURL =
734             layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs" +
735                 StringPool.SLASH + entry.getEntryId();
736 
737         String subject = null;
738         String body = null;
739 
740         if (serviceContext.isCommandUpdate()) {
741             subject = BlogsUtil.getEmailEntryUpdatedSubject(preferences);
742             body = BlogsUtil.getEmailEntryUpdatedBody(preferences);
743         }
744         else {
745             subject = BlogsUtil.getEmailEntryAddedSubject(preferences);
746             body = BlogsUtil.getEmailEntryAddedBody(preferences);
747         }
748 
749         subject = StringUtil.replace(
750             subject,
751             new String[] {
752                 "[$BLOGS_ENTRY_USER_ADDRESS$]",
753                 "[$BLOGS_ENTRY_USER_NAME$]",
754                 "[$BLOGS_ENTRY_URL$]",
755                 "[$COMPANY_ID$]",
756                 "[$COMPANY_MX$]",
757                 "[$COMPANY_NAME$]",
758                 "[$COMMUNITY_NAME$]",
759                 "[$FROM_ADDRESS$]",
760                 "[$FROM_NAME$]",
761                 "[$PORTAL_URL$]",
762                 "[$PORTLET_NAME$]"
763             },
764             new String[] {
765                 emailAddress,
766                 fullName,
767                 entryURL,
768                 String.valueOf(company.getCompanyId()),
769                 company.getMx(),
770                 company.getName(),
771                 group.getName(),
772                 fromAddress,
773                 fromName,
774                 company.getVirtualHost(),
775                 portletName
776             });
777 
778         body = StringUtil.replace(
779             body,
780             new String[] {
781                 "[$BLOGS_ENTRY_USER_ADDRESS$]",
782                 "[$BLOGS_ENTRY_USER_NAME$]",
783                 "[$BLOGS_ENTRY_URL$]",
784                 "[$COMPANY_ID$]",
785                 "[$COMPANY_MX$]",
786                 "[$COMPANY_NAME$]",
787                 "[$COMMUNITY_NAME$]",
788                 "[$FROM_ADDRESS$]",
789                 "[$FROM_NAME$]",
790                 "[$PORTAL_URL$]",
791                 "[$PORTLET_NAME$]"
792             },
793             new String[] {
794                 emailAddress,
795                 fullName,
796                 entryURL,
797                 String.valueOf(company.getCompanyId()),
798                 company.getMx(),
799                 company.getName(),
800                 group.getName(),
801                 fromAddress,
802                 fromName,
803                 company.getVirtualHost(),
804                 portletName
805             });
806 
807         Message message = new Message();
808 
809         message.put("companyId", entry.getCompanyId());
810         message.put("userId", entry.getUserId());
811         message.put("groupId", entry.getGroupId());
812         message.put("entryId", entry.getEntryId());
813         message.put("fromName", fromName);
814         message.put("fromAddress", fromAddress);
815         message.put("subject", subject);
816         message.put("body", body);
817         message.put("replyToAddress", fromAddress);
818         message.put(
819             "mailId", BlogsUtil.getMailId(company.getMx(), entry.getEntryId()));
820         message.put("htmlFormat", Boolean.TRUE);
821 
822         MessageBusUtil.sendMessage(DestinationNames.BLOGS, message);
823     }
824 
825     protected void pingGoogle(BlogsEntry entry, ServiceContext serviceContext)
826         throws PortalException, SystemException {
827 
828         if (!PropsValues.BLOGS_PING_GOOGLE_ENABLED || !entry.isApproved()) {
829             return;
830         }
831 
832         String layoutFullURL = PortalUtil.getLayoutFullURL(
833             serviceContext.getScopeGroupId(), PortletKeys.BLOGS);
834 
835         if (Validator.isNull(layoutFullURL)) {
836             return;
837         }
838 
839         if (layoutFullURL.contains("://localhost")) {
840             if (_log.isDebugEnabled()) {
841                 _log.debug(
842                     "Not pinging Google because of localhost URL " +
843                         layoutFullURL);
844             }
845 
846             return;
847         }
848 
849         Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
850 
851         StringBundler sb = new StringBundler(6);
852 
853         String name = group.getDescriptiveName();
854         String url = layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs";
855         String changesURL =
856             layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/rss";
857 
858         sb.append("http://blogsearch.google.com/ping?name=");
859         sb.append(HttpUtil.encodeURL(name));
860         sb.append("&url=");
861         sb.append(HttpUtil.encodeURL(url));
862         sb.append("&changesURL=");
863         sb.append(HttpUtil.encodeURL(changesURL));
864 
865         String location = sb.toString();
866 
867         if (_log.isInfoEnabled()) {
868             _log.info("Pinging Google at " + location);
869         }
870 
871         try {
872             String response = HttpUtil.URLtoString(sb.toString());
873 
874             if (_log.isInfoEnabled()) {
875                 _log.info("Google ping response: " + response);
876             }
877         }
878         catch (IOException ioe) {
879             _log.error("Unable to ping Google at " + location, ioe);
880         }
881     }
882 
883     protected void pingPingback(
884         BlogsEntry entry, ServiceContext serviceContext) {
885 
886         if (!PropsValues.BLOGS_PINGBACK_ENABLED ||
887             !entry.isAllowPingbacks() || !entry.isApproved()) {
888 
889             return;
890         }
891 
892         String layoutFullURL = serviceContext.getLayoutFullURL();
893 
894         if (Validator.isNull(layoutFullURL)) {
895             return;
896         }
897 
898         String sourceUri =
899             layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
900                 entry.getUrlTitle();
901 
902         Source source = new Source(entry.getContent());
903 
904         List<StartTag> tags = source.getAllStartTags("a");
905 
906         for (StartTag tag : tags) {
907             String targetUri = tag.getAttributeValue("href");
908 
909             if (Validator.isNotNull(targetUri)) {
910                 try {
911                     LinkbackProducerUtil.sendPingback(sourceUri, targetUri);
912                 }
913                 catch (Exception e) {
914                     _log.error("Error while sending pingback " + targetUri, e);
915                 }
916             }
917         }
918     }
919 
920     protected void pingTrackbacks(
921             BlogsEntry entry, String[] trackbacks, boolean pingOldTrackbacks,
922             ServiceContext serviceContext)
923         throws SystemException {
924 
925         if (!PropsValues.BLOGS_TRACKBACK_ENABLED ||
926             !entry.isAllowTrackbacks() || !entry.isApproved()) {
927 
928             return;
929         }
930 
931         String layoutFullURL = serviceContext.getLayoutFullURL();
932 
933         if (Validator.isNull(layoutFullURL)) {
934             return;
935         }
936 
937         Map<String, String> parts = new HashMap<String, String>();
938 
939         String excerpt = StringUtil.shorten(
940             HtmlUtil.extractText(entry.getContent()),
941             PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH);
942         String url =
943             layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
944                 entry.getUrlTitle();
945 
946         parts.put("title", entry.getTitle());
947         parts.put("excerpt", excerpt);
948         parts.put("url", url);
949         parts.put("blog_name", entry.getUserName());
950 
951         Set<String> trackbacksSet = null;
952 
953         if (Validator.isNotNull(trackbacks)) {
954             trackbacksSet = SetUtil.fromArray(trackbacks);
955         }
956         else {
957             trackbacksSet = new HashSet<String>();
958         }
959 
960         if (pingOldTrackbacks) {
961             trackbacksSet.addAll(
962                 SetUtil.fromArray(StringUtil.split(entry.getTrackbacks())));
963 
964             entry.setTrackbacks(StringPool.BLANK);
965 
966             blogsEntryPersistence.update(entry, false);
967         }
968 
969         Set<String> oldTrackbacks = SetUtil.fromArray(
970             StringUtil.split(entry.getTrackbacks()));
971 
972         Set<String> validTrackbacks = new HashSet<String>();
973 
974         for (String trackback : trackbacksSet) {
975             if (oldTrackbacks.contains(trackback)) {
976                 continue;
977             }
978 
979             try {
980                 if (LinkbackProducerUtil.sendTrackback(trackback, parts)) {
981                     validTrackbacks.add(trackback);
982                 }
983             }
984             catch (Exception e) {
985                 _log.error("Error while sending trackback at " + trackback, e);
986             }
987         }
988 
989         if (!validTrackbacks.isEmpty()) {
990             String newTrackbacks = StringUtil.merge(validTrackbacks);
991 
992             if (Validator.isNotNull(entry.getTrackbacks())) {
993                 newTrackbacks += StringPool.COMMA + entry.getTrackbacks();
994             }
995 
996             entry.setTrackbacks(newTrackbacks);
997 
998             blogsEntryPersistence.update(entry, false);
999         }
1000    }
1001
1002    protected void validate(String title, String content)
1003        throws PortalException {
1004
1005        if (Validator.isNull(title)) {
1006            throw new EntryTitleException();
1007        }
1008        else if (Validator.isNull(content)) {
1009            throw new EntryContentException();
1010        }
1011    }
1012
1013    private static Log _log = LogFactoryUtil.getLog(
1014        BlogsEntryLocalServiceImpl.class);
1015
1016}