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