001    /**
002     * Copyright (c) 2000-2010 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.blogs.service.impl;
016    
017    import com.liferay.portal.NoSuchUserException;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.messaging.DestinationNames;
023    import com.liferay.portal.kernel.messaging.Message;
024    import com.liferay.portal.kernel.messaging.MessageBusUtil;
025    import com.liferay.portal.kernel.search.Indexer;
026    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
027    import com.liferay.portal.kernel.util.ContentTypes;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.HtmlUtil;
030    import com.liferay.portal.kernel.util.HttpUtil;
031    import com.liferay.portal.kernel.util.LocaleUtil;
032    import com.liferay.portal.kernel.util.OrderByComparator;
033    import com.liferay.portal.kernel.util.SetUtil;
034    import com.liferay.portal.kernel.util.StringBundler;
035    import com.liferay.portal.kernel.util.StringPool;
036    import com.liferay.portal.kernel.util.StringUtil;
037    import com.liferay.portal.kernel.util.Validator;
038    import com.liferay.portal.kernel.workflow.WorkflowConstants;
039    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
040    import com.liferay.portal.model.Company;
041    import com.liferay.portal.model.Group;
042    import com.liferay.portal.model.ResourceConstants;
043    import com.liferay.portal.model.User;
044    import com.liferay.portal.security.permission.ActionKeys;
045    import com.liferay.portal.service.ServiceContext;
046    import com.liferay.portal.service.ServiceContextUtil;
047    import com.liferay.portal.util.Portal;
048    import com.liferay.portal.util.PortalUtil;
049    import com.liferay.portal.util.PortletKeys;
050    import com.liferay.portal.util.PropsValues;
051    import com.liferay.portlet.blogs.EntryContentException;
052    import com.liferay.portlet.blogs.EntryDisplayDateException;
053    import com.liferay.portlet.blogs.EntryTitleException;
054    import com.liferay.portlet.blogs.model.BlogsEntry;
055    import com.liferay.portlet.blogs.service.base.BlogsEntryLocalServiceBaseImpl;
056    import com.liferay.portlet.blogs.social.BlogsActivityKeys;
057    import com.liferay.portlet.blogs.util.BlogsUtil;
058    import com.liferay.portlet.blogs.util.LinkbackProducerUtil;
059    import com.liferay.portlet.blogs.util.comparator.EntryDisplayDateComparator;
060    
061    import java.io.IOException;
062    
063    import java.util.Date;
064    import java.util.HashMap;
065    import java.util.HashSet;
066    import java.util.List;
067    import java.util.Map;
068    import java.util.Set;
069    
070    import javax.portlet.PortletPreferences;
071    
072    import net.htmlparser.jericho.Source;
073    import net.htmlparser.jericho.StartTag;
074    
075    /**
076     * @author Brian Wing Shun Chan
077     * @author Wilson S. Man
078     * @author Raymond Augé
079     * @author Thiago Moreira
080     */
081    public class BlogsEntryLocalServiceImpl extends BlogsEntryLocalServiceBaseImpl {
082    
083            public BlogsEntry addEntry(
084                            long userId, String title, String content, int displayDateMonth,
085                            int displayDateDay, int displayDateYear, int displayDateHour,
086                            int displayDateMinute, boolean allowPingbacks,
087                            boolean allowTrackbacks, String[] trackbacks,
088                            ServiceContext serviceContext)
089                    throws PortalException, SystemException {
090    
091                    // Entry
092    
093                    User user = userPersistence.findByPrimaryKey(userId);
094                    long groupId = serviceContext.getScopeGroupId();
095    
096                    Date displayDate = PortalUtil.getDate(
097                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
098                            displayDateMinute, user.getTimeZone(),
099                            new EntryDisplayDateException());
100    
101                    Date now = new Date();
102    
103                    validate(title, content);
104    
105                    long entryId = counterLocalService.increment();
106    
107                    BlogsEntry entry = blogsEntryPersistence.create(entryId);
108    
109                    entry.setUuid(serviceContext.getUuid());
110                    entry.setGroupId(groupId);
111                    entry.setCompanyId(user.getCompanyId());
112                    entry.setUserId(user.getUserId());
113                    entry.setUserName(user.getFullName());
114                    entry.setCreateDate(serviceContext.getCreateDate(now));
115                    entry.setModifiedDate(serviceContext.getModifiedDate(now));
116                    entry.setTitle(title);
117                    entry.setUrlTitle(getUniqueUrlTitle(entryId, groupId, title));
118                    entry.setContent(content);
119                    entry.setDisplayDate(displayDate);
120                    entry.setAllowPingbacks(allowPingbacks);
121                    entry.setAllowTrackbacks(allowTrackbacks);
122                    entry.setStatus(WorkflowConstants.STATUS_DRAFT);
123                    entry.setStatusDate(serviceContext.getModifiedDate(now));
124                    entry.setExpandoBridgeAttributes(serviceContext);
125    
126                    blogsEntryPersistence.update(entry, false);
127    
128                    // Resources
129    
130                    if (serviceContext.getAddCommunityPermissions() ||
131                            serviceContext.getAddGuestPermissions()) {
132    
133                            addEntryResources(
134                                    entry, serviceContext.getAddCommunityPermissions(),
135                                    serviceContext.getAddGuestPermissions());
136                    }
137                    else {
138                            addEntryResources(
139                                    entry, serviceContext.getCommunityPermissions(),
140                                    serviceContext.getGuestPermissions());
141                    }
142    
143                    // Asset
144    
145                    updateAsset(
146                            userId, entry, serviceContext.getAssetCategoryIds(),
147                            serviceContext.getAssetTagNames());
148    
149                    // Message boards
150    
151                    if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
152                            mbMessageLocalService.addDiscussionMessage(
153                                    userId, entry.getUserName(), groupId,
154                                    BlogsEntry.class.getName(), entryId,
155                                    WorkflowConstants.ACTION_PUBLISH);
156                    }
157    
158                    // Workflow
159    
160                    if ((trackbacks != null) && (trackbacks.length > 0)) {
161                            serviceContext.setAttribute("trackbacks", trackbacks);
162                    }
163                    else {
164                            serviceContext.setAttribute("trackbacks", null);
165                    }
166    
167                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
168                            user.getCompanyId(), groupId, userId, BlogsEntry.class.getName(),
169                            entry.getEntryId(), entry, serviceContext);
170    
171                    return entry;
172            }
173    
174            public void addEntryResources(
175                            BlogsEntry entry, boolean addCommunityPermissions,
176                            boolean addGuestPermissions)
177                    throws PortalException, SystemException {
178    
179                    resourceLocalService.addResources(
180                            entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
181                            BlogsEntry.class.getName(), entry.getEntryId(), false,
182                            addCommunityPermissions, addGuestPermissions);
183            }
184    
185            public void addEntryResources(
186                            BlogsEntry entry, String[] communityPermissions,
187                            String[] guestPermissions)
188                    throws PortalException, SystemException {
189    
190                    resourceLocalService.addModelResources(
191                            entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
192                            BlogsEntry.class.getName(), entry.getEntryId(),
193                            communityPermissions, guestPermissions);
194            }
195    
196            public void addEntryResources(
197                            long entryId, boolean addCommunityPermissions,
198                            boolean addGuestPermissions)
199                    throws PortalException, SystemException {
200    
201                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
202    
203                    addEntryResources(entry, addCommunityPermissions, addGuestPermissions);
204            }
205    
206            public void addEntryResources(
207                            long entryId, String[] communityPermissions,
208                            String[] guestPermissions)
209                    throws PortalException, SystemException {
210    
211                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
212    
213                    addEntryResources(entry, communityPermissions, guestPermissions);
214            }
215    
216            public void deleteEntries(long groupId)
217                    throws PortalException, SystemException {
218    
219                    for (BlogsEntry entry : blogsEntryPersistence.findByGroupId(groupId)) {
220                            deleteEntry(entry);
221                    }
222            }
223    
224            public void deleteEntry(BlogsEntry entry)
225                    throws PortalException, SystemException {
226    
227                    // Entry
228    
229                    blogsEntryPersistence.remove(entry);
230    
231                    // Resources
232    
233                    resourceLocalService.deleteResource(
234                            entry.getCompanyId(), BlogsEntry.class.getName(),
235                            ResourceConstants.SCOPE_INDIVIDUAL, entry.getEntryId());
236    
237                    // Statistics
238    
239                    blogsStatsUserLocalService.updateStatsUser(
240                            entry.getGroupId(), entry.getUserId());
241    
242                    // Asset
243    
244                    assetEntryLocalService.deleteEntry(
245                            BlogsEntry.class.getName(), entry.getEntryId());
246    
247                    // Expando
248    
249                    expandoValueLocalService.deleteValues(
250                            BlogsEntry.class.getName(), entry.getEntryId());
251    
252                    // Message boards
253    
254                    mbMessageLocalService.deleteDiscussionMessages(
255                            BlogsEntry.class.getName(), entry.getEntryId());
256    
257                    // Ratings
258    
259                    ratingsStatsLocalService.deleteStats(
260                            BlogsEntry.class.getName(), entry.getEntryId());
261    
262                    // Social
263    
264                    socialActivityLocalService.deleteActivities(
265                            BlogsEntry.class.getName(), entry.getEntryId());
266    
267                    // Indexer
268    
269                    Indexer indexer = IndexerRegistryUtil.getIndexer(BlogsEntry.class);
270    
271                    indexer.delete(entry);
272    
273                    // Workflow
274    
275                    workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
276                            entry.getCompanyId(), entry.getGroupId(),
277                            BlogsEntry.class.getName(), entry.getEntryId());
278            }
279    
280            public void deleteEntry(long entryId)
281                    throws PortalException, SystemException {
282    
283                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
284    
285                    deleteEntry(entry);
286            }
287    
288            public List<BlogsEntry> getCompanyEntries(
289                            long companyId, int status, int start, int end)
290                    throws SystemException {
291    
292                    if (status == WorkflowConstants.STATUS_ANY) {
293                            return blogsEntryPersistence.findByC_LtD(
294                                    companyId, new Date(), start, end);
295                    }
296                    else {
297                            return blogsEntryPersistence.findByC_LtD_S(
298                                    companyId, new Date(), status, start, end);
299                    }
300            }
301    
302            public List<BlogsEntry> getCompanyEntries(
303                            long companyId, int status, int start, int end,
304                            OrderByComparator obc)
305                    throws SystemException {
306    
307                    if (status == WorkflowConstants.STATUS_ANY) {
308                            return blogsEntryPersistence.findByC_LtD(
309                                    companyId, new Date(), start, end, obc);
310                    }
311                    else {
312                            return blogsEntryPersistence.findByC_LtD_S(
313                                    companyId, new Date(), status, start, end, obc);
314                    }
315            }
316    
317            public int getCompanyEntriesCount(long companyId, int status)
318                    throws SystemException {
319    
320                    if (status == WorkflowConstants.STATUS_ANY) {
321                            return blogsEntryPersistence.countByC_LtD(
322                                    companyId, new Date());
323                    }
324                    else {
325                            return blogsEntryPersistence.countByC_LtD_S(
326                                    companyId, new Date(), status);
327                    }
328            }
329    
330            public BlogsEntry[] getEntriesPrevAndNext(long entryId)
331                    throws PortalException, SystemException {
332    
333                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
334    
335                    return blogsEntryPersistence.findByG_S_PrevAndNext(
336                            entry.getEntryId(), entry.getGroupId(),
337                            WorkflowConstants.STATUS_APPROVED,
338                            new EntryDisplayDateComparator(true));
339            }
340    
341            public BlogsEntry getEntry(long entryId)
342                    throws PortalException, SystemException {
343    
344                    return blogsEntryPersistence.findByPrimaryKey(entryId);
345            }
346    
347            public BlogsEntry getEntry(long groupId, String urlTitle)
348                    throws PortalException, SystemException {
349    
350                    return blogsEntryPersistence.findByG_UT(groupId, urlTitle);
351            }
352    
353            public List<BlogsEntry> getGroupEntries(
354                            long groupId, int status, int start, int end)
355                    throws SystemException {
356    
357                    if (status == WorkflowConstants.STATUS_ANY) {
358                            return blogsEntryPersistence.findByG_LtD(
359                                    groupId, new Date(), start, end);
360                    }
361                    else {
362                            return blogsEntryPersistence.findByG_LtD_S(
363                                    groupId, new Date(), status, start, end);
364                    }
365            }
366    
367            public List<BlogsEntry> getGroupEntries(
368                            long groupId, int status, int start, int end, OrderByComparator obc)
369                    throws SystemException {
370    
371                    if (status == WorkflowConstants.STATUS_ANY) {
372                            return blogsEntryPersistence.findByG_LtD(
373                                    groupId, new Date(), start, end, obc);
374                    }
375                    else {
376                            return blogsEntryPersistence.findByG_LtD_S(
377                                    groupId, new Date(), status, start, end, obc);
378                    }
379            }
380    
381            public int getGroupEntriesCount(long groupId, int status)
382                    throws SystemException {
383    
384                    if (status == WorkflowConstants.STATUS_ANY) {
385                            return blogsEntryPersistence.countByG_LtD(groupId, new Date());
386                    }
387                    else {
388                            return blogsEntryPersistence.countByG_LtD_S(
389                                    groupId, new Date(), status);
390                    }
391            }
392    
393            public List<BlogsEntry> getGroupsEntries(
394                            long companyId, long groupId, int status, int start, int end)
395                    throws SystemException {
396    
397                    return blogsEntryFinder.findByGroupIds(
398                            companyId, groupId, status, start, end);
399            }
400    
401            public List<BlogsEntry> getGroupUserEntries(
402                            long groupId, long userId, int status, int start, int end)
403                    throws SystemException {
404    
405                    if (status == WorkflowConstants.STATUS_ANY) {
406                            return blogsEntryPersistence.findByG_U_LtD(
407                                    groupId, userId, new Date(), start, end);
408                    }
409                    else {
410                            return blogsEntryPersistence.findByG_U_LtD_S(
411                                    groupId, userId, new Date(), status, start, end);
412                    }
413            }
414    
415            public List<BlogsEntry> getGroupUserEntries(
416                            long groupId, long userId, int status, int start, int end,
417                            OrderByComparator obc)
418                    throws SystemException {
419    
420                    if (status == WorkflowConstants.STATUS_ANY) {
421                            return blogsEntryPersistence.findByG_U_LtD(
422                                    groupId, userId, new Date(), start, end, obc);
423                    }
424                    else {
425                            return blogsEntryPersistence.findByG_U_LtD_S(
426                                    groupId, userId, new Date(), status, start, end, obc);
427                    }
428            }
429    
430            public int getGroupUserEntriesCount(long groupId, long userId, int status)
431                    throws SystemException {
432    
433                    if (status == WorkflowConstants.STATUS_ANY) {
434                            return blogsEntryPersistence.countByG_U_LtD(
435                                    groupId, userId, new Date());
436                    }
437                    else {
438                            return blogsEntryPersistence.countByG_U_LtD_S(
439                                    groupId, userId, new Date(), status);
440                    }
441            }
442    
443            public List<BlogsEntry> getNoAssetEntries() throws SystemException {
444                    return blogsEntryFinder.findByNoAssets();
445            }
446    
447            public List<BlogsEntry> getOrganizationEntries(
448                            long organizationId, int status, int start, int end)
449                    throws SystemException {
450    
451                    return blogsEntryFinder.findByOrganizationId(
452                            organizationId, new Date(), status, start, end);
453            }
454    
455            public int getOrganizationEntriesCount(long organizationId, int status)
456                    throws SystemException {
457    
458                    return blogsEntryFinder.countByOrganizationId(
459                            organizationId, new Date(), status);
460            }
461    
462            public void updateAsset(
463                            long userId, BlogsEntry entry, long[] assetCategoryIds,
464                            String[] assetTagNames)
465                    throws PortalException, SystemException {
466    
467                    boolean visible = false;
468    
469                    if (entry.getStatus() == WorkflowConstants.STATUS_APPROVED) {
470                            visible = true;
471                    }
472    
473                    String summary = HtmlUtil.extractText(
474                            StringUtil.shorten(entry.getContent(), 500));
475    
476                    assetEntryLocalService.updateEntry(
477                            userId, entry.getGroupId(), BlogsEntry.class.getName(),
478                            entry.getEntryId(), entry.getUuid(), assetCategoryIds,
479                            assetTagNames, visible, null, null, entry.getDisplayDate(), null,
480                            ContentTypes.TEXT_HTML, entry.getTitle(), null, summary, null, 0, 0,
481                            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 (status == WorkflowConstants.STATUS_APPROVED) {
597    
598                            // Statistics
599    
600                            blogsStatsUserLocalService.updateStatsUser(
601                                    entry.getGroupId(), entry.getUserId(), entry.getDisplayDate());
602    
603                            if (oldStatus != WorkflowConstants.STATUS_APPROVED) {
604    
605                                    // Asset
606    
607                                    assetEntryLocalService.updateVisible(
608                                            BlogsEntry.class.getName(), entryId, true);
609    
610                                    // Social
611    
612                                    socialActivityLocalService.addUniqueActivity(
613                                            entry.getUserId(), entry.getGroupId(),
614                                            BlogsEntry.class.getName(), entryId,
615                                            BlogsActivityKeys.ADD_ENTRY, StringPool.BLANK, 0);
616    
617                                    socialEquityLogLocalService.addEquityLogs(
618                                            userId, BlogsEntry.class.getName(), entryId,
619                                            ActionKeys.ADD_ENTRY);
620    
621                                    // Subscriptions
622    
623                                    notifySubscribers(entry, serviceContext);
624                            }
625    
626                            // Indexer
627    
628                            indexer.reindex(entry);
629    
630                            // Ping
631    
632                            String[] trackbacks = (String[])serviceContext.getAttribute(
633                                    "trackbacks");
634                            Boolean pingOldTrackbacks = GetterUtil.getBoolean(
635                                    (String)serviceContext.getAttribute("pingOldTrackbacks"));
636    
637                            pingGoogle(entry, serviceContext);
638                            pingPingback(entry, serviceContext);
639                            pingTrackbacks(
640                                    entry, trackbacks, pingOldTrackbacks, serviceContext);
641                    }
642                    else if (status != WorkflowConstants.STATUS_APPROVED) {
643    
644                            // Asset
645    
646                            assetEntryLocalService.updateVisible(
647                                    BlogsEntry.class.getName(), entryId, false);
648    
649                            // Indexer
650    
651                            indexer.delete(entry);
652                    }
653    
654                    return entry;
655            }
656    
657            protected String getUniqueUrlTitle(
658                            long entryId, long groupId, String title)
659                    throws SystemException {
660    
661                    String urlTitle = BlogsUtil.getUrlTitle(entryId, title);
662    
663                    String newUrlTitle = urlTitle;
664    
665                    for (int i = 1;; i++) {
666                            BlogsEntry entry = blogsEntryPersistence.fetchByG_UT(
667                                    groupId, newUrlTitle);
668    
669                            if ((entry == null) || (entry.getEntryId() == entryId)) {
670                                    break;
671                            }
672                            else {
673                                    newUrlTitle = urlTitle + StringPool.DASH + i;
674                            }
675                    }
676    
677                    return newUrlTitle;
678            }
679    
680            protected void notifySubscribers(
681                            BlogsEntry entry, ServiceContext serviceContext)
682                    throws PortalException, SystemException {
683    
684                    if (!entry.isApproved()) {
685                            return;
686                    }
687    
688                    String layoutFullURL = PortalUtil.getLayoutFullURL(
689                            serviceContext.getScopeGroupId(), PortletKeys.BLOGS);
690    
691                    if (Validator.isNull(layoutFullURL)) {
692                            return;
693                    }
694    
695                    PortletPreferences preferences =
696                            ServiceContextUtil.getPortletPreferences(serviceContext);
697    
698                    if (preferences == null) {
699                            long ownerId = entry.getGroupId();
700                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
701                            long plid = PortletKeys.PREFS_PLID_SHARED;
702                            String portletId = PortletKeys.BLOGS;
703                            String defaultPreferences = null;
704    
705                            preferences = portletPreferencesLocalService.getPreferences(
706                                    entry.getCompanyId(), ownerId, ownerType, plid, portletId,
707                                    defaultPreferences);
708                    }
709    
710                    if (serviceContext.isCommandAdd() &&
711                            BlogsUtil.getEmailEntryAddedEnabled(preferences)) {
712                    }
713                    else if (serviceContext.isCommandUpdate() &&
714                                     BlogsUtil.getEmailEntryUpdatedEnabled(preferences)) {
715                    }
716                    else {
717                            return;
718                    }
719    
720                    Company company = companyPersistence.findByPrimaryKey(
721                            entry.getCompanyId());
722    
723                    Group group = groupPersistence.findByPrimaryKey(
724                            serviceContext.getScopeGroupId());
725    
726                    String emailAddress = StringPool.BLANK;
727                    String fullName = entry.getUserName();
728    
729                    try {
730                            User user = userPersistence.findByPrimaryKey(entry.getUserId());
731    
732                            emailAddress = user.getEmailAddress();
733                            fullName = user.getFullName();
734                    }
735                    catch (NoSuchUserException nsue) {
736                    }
737    
738                    String portletName = PortalUtil.getPortletTitle(
739                            PortletKeys.BLOGS, LocaleUtil.getDefault());
740    
741                    String fromName = BlogsUtil.getEmailFromName(preferences);
742                    String fromAddress = BlogsUtil.getEmailFromAddress(preferences);
743    
744                    fromName = StringUtil.replace(
745                            fromName,
746                            new String[] {
747                                    "[$BLOGS_ENTRY_USER_ADDRESS$]",
748                                    "[$BLOGS_ENTRY_USER_NAME$]",
749                                    "[$COMPANY_ID$]",
750                                    "[$COMPANY_MX$]",
751                                    "[$COMPANY_NAME$]",
752                                    "[$COMMUNITY_NAME$]",
753                                    "[$PORTLET_NAME$]"
754                            },
755                            new String[] {
756                                    emailAddress,
757                                    fullName,
758                                    String.valueOf(company.getCompanyId()),
759                                    company.getMx(),
760                                    company.getName(),
761                                    group.getName(),
762                                    portletName
763                            });
764    
765                    fromAddress = StringUtil.replace(
766                            fromAddress,
767                            new String[] {
768                                    "[$BLOGS_ENTRY_USER_ADDRESS$]",
769                                    "[$BLOGS_ENTRY_USER_NAME$]",
770                                    "[$COMPANY_ID$]",
771                                    "[$COMPANY_MX$]",
772                                    "[$COMPANY_NAME$]",
773                                    "[$COMMUNITY_NAME$]",
774                                    "[$PORTLET_NAME$]"
775                            },
776                            new String[] {
777                                    emailAddress,
778                                    fullName,
779                                    String.valueOf(company.getCompanyId()),
780                                    company.getMx(),
781                                    company.getName(),
782                                    group.getName(),
783                                    portletName
784                            });
785    
786                    String entryURL =
787                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs" +
788                                    StringPool.SLASH + entry.getEntryId();
789    
790                    String subject = null;
791                    String body = null;
792    
793                    if (serviceContext.isCommandUpdate()) {
794                            subject = BlogsUtil.getEmailEntryUpdatedSubject(preferences);
795                            body = BlogsUtil.getEmailEntryUpdatedBody(preferences);
796                    }
797                    else {
798                            subject = BlogsUtil.getEmailEntryAddedSubject(preferences);
799                            body = BlogsUtil.getEmailEntryAddedBody(preferences);
800                    }
801    
802                    subject = StringUtil.replace(
803                            subject,
804                            new String[] {
805                                    "[$BLOGS_ENTRY_USER_ADDRESS$]",
806                                    "[$BLOGS_ENTRY_USER_NAME$]",
807                                    "[$BLOGS_ENTRY_URL$]",
808                                    "[$COMPANY_ID$]",
809                                    "[$COMPANY_MX$]",
810                                    "[$COMPANY_NAME$]",
811                                    "[$COMMUNITY_NAME$]",
812                                    "[$FROM_ADDRESS$]",
813                                    "[$FROM_NAME$]",
814                                    "[$PORTAL_URL$]",
815                                    "[$PORTLET_NAME$]"
816                            },
817                            new String[] {
818                                    emailAddress,
819                                    fullName,
820                                    entryURL,
821                                    String.valueOf(company.getCompanyId()),
822                                    company.getMx(),
823                                    company.getName(),
824                                    group.getName(),
825                                    fromAddress,
826                                    fromName,
827                                    company.getVirtualHost(),
828                                    portletName
829                            });
830    
831                    body = StringUtil.replace(
832                            body,
833                            new String[] {
834                                    "[$BLOGS_ENTRY_USER_ADDRESS$]",
835                                    "[$BLOGS_ENTRY_USER_NAME$]",
836                                    "[$BLOGS_ENTRY_URL$]",
837                                    "[$COMPANY_ID$]",
838                                    "[$COMPANY_MX$]",
839                                    "[$COMPANY_NAME$]",
840                                    "[$COMMUNITY_NAME$]",
841                                    "[$FROM_ADDRESS$]",
842                                    "[$FROM_NAME$]",
843                                    "[$PORTAL_URL$]",
844                                    "[$PORTLET_NAME$]"
845                            },
846                            new String[] {
847                                    emailAddress,
848                                    fullName,
849                                    entryURL,
850                                    String.valueOf(company.getCompanyId()),
851                                    company.getMx(),
852                                    company.getName(),
853                                    group.getName(),
854                                    fromAddress,
855                                    fromName,
856                                    company.getVirtualHost(),
857                                    portletName
858                            });
859    
860                    Message message = new Message();
861    
862                    message.put("companyId", entry.getCompanyId());
863                    message.put("userId", entry.getUserId());
864                    message.put("groupId", entry.getGroupId());
865                    message.put("entryId", entry.getEntryId());
866                    message.put("fromName", fromName);
867                    message.put("fromAddress", fromAddress);
868                    message.put("subject", subject);
869                    message.put("body", body);
870                    message.put("replyToAddress", fromAddress);
871                    message.put(
872                            "mailId", BlogsUtil.getMailId(company.getMx(), entry.getEntryId()));
873                    message.put("htmlFormat", Boolean.TRUE);
874    
875                    MessageBusUtil.sendMessage(DestinationNames.BLOGS, message);
876            }
877    
878            protected void pingGoogle(BlogsEntry entry, ServiceContext serviceContext)
879                    throws PortalException, SystemException {
880    
881                    if (!PropsValues.BLOGS_PING_GOOGLE_ENABLED || !entry.isApproved()) {
882                            return;
883                    }
884    
885                    String layoutFullURL = PortalUtil.getLayoutFullURL(
886                            serviceContext.getScopeGroupId(), PortletKeys.BLOGS);
887    
888                    if (Validator.isNull(layoutFullURL)) {
889                            return;
890                    }
891    
892                    if (layoutFullURL.contains("://localhost")) {
893                            if (_log.isDebugEnabled()) {
894                                    _log.debug(
895                                            "Not pinging Google because of localhost URL " +
896                                                    layoutFullURL);
897                            }
898    
899                            return;
900                    }
901    
902                    Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
903    
904                    StringBundler sb = new StringBundler(6);
905    
906                    String name = group.getDescriptiveName();
907                    String url = layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs";
908                    String changesURL =
909                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/rss";
910    
911                    sb.append("http://blogsearch.google.com/ping?name=");
912                    sb.append(HttpUtil.encodeURL(name));
913                    sb.append("&url=");
914                    sb.append(HttpUtil.encodeURL(url));
915                    sb.append("&changesURL=");
916                    sb.append(HttpUtil.encodeURL(changesURL));
917    
918                    String location = sb.toString();
919    
920                    if (_log.isInfoEnabled()) {
921                            _log.info("Pinging Google at " + location);
922                    }
923    
924                    try {
925                            String response = HttpUtil.URLtoString(sb.toString());
926    
927                            if (_log.isInfoEnabled()) {
928                                    _log.info("Google ping response: " + response);
929                            }
930                    }
931                    catch (IOException ioe) {
932                            _log.error("Unable to ping Google at " + location, ioe);
933                    }
934            }
935    
936            protected void pingPingback(
937                    BlogsEntry entry, ServiceContext serviceContext) {
938    
939                    if (!PropsValues.BLOGS_PINGBACK_ENABLED ||
940                            !entry.isAllowPingbacks() || !entry.isApproved()) {
941    
942                            return;
943                    }
944    
945                    String layoutFullURL = serviceContext.getLayoutFullURL();
946    
947                    if (Validator.isNull(layoutFullURL)) {
948                            return;
949                    }
950    
951                    String sourceUri =
952                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
953                                    entry.getUrlTitle();
954    
955                    Source source = new Source(entry.getContent());
956    
957                    List<StartTag> tags = source.getAllStartTags("a");
958    
959                    for (StartTag tag : tags) {
960                            String targetUri = tag.getAttributeValue("href");
961    
962                            if (Validator.isNotNull(targetUri)) {
963                                    try {
964                                            LinkbackProducerUtil.sendPingback(sourceUri, targetUri);
965                                    }
966                                    catch (Exception e) {
967                                            _log.error("Error while sending pingback " + targetUri, e);
968                                    }
969                            }
970                    }
971            }
972    
973            protected void pingTrackbacks(
974                            BlogsEntry entry, String[] trackbacks, boolean pingOldTrackbacks,
975                            ServiceContext serviceContext)
976                    throws SystemException {
977    
978                    if (!PropsValues.BLOGS_TRACKBACK_ENABLED ||
979                            !entry.isAllowTrackbacks() || !entry.isApproved()) {
980    
981                            return;
982                    }
983    
984                    String layoutFullURL = serviceContext.getLayoutFullURL();
985    
986                    if (Validator.isNull(layoutFullURL)) {
987                            return;
988                    }
989    
990                    Map<String, String> parts = new HashMap<String, String>();
991    
992                    String excerpt = StringUtil.shorten(
993                            HtmlUtil.extractText(entry.getContent()),
994                            PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH);
995                    String url =
996                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
997                                    entry.getUrlTitle();
998    
999                    parts.put("title", entry.getTitle());
1000                    parts.put("excerpt", excerpt);
1001                    parts.put("url", url);
1002                    parts.put("blog_name", entry.getUserName());
1003    
1004                    Set<String> trackbacksSet = null;
1005    
1006                    if (Validator.isNotNull(trackbacks)) {
1007                            trackbacksSet = SetUtil.fromArray(trackbacks);
1008                    }
1009                    else {
1010                            trackbacksSet = new HashSet<String>();
1011                    }
1012    
1013                    if (pingOldTrackbacks) {
1014                            trackbacksSet.addAll(
1015                                    SetUtil.fromArray(StringUtil.split(entry.getTrackbacks())));
1016    
1017                            entry.setTrackbacks(StringPool.BLANK);
1018    
1019                            blogsEntryPersistence.update(entry, false);
1020                    }
1021    
1022                    Set<String> oldTrackbacks = SetUtil.fromArray(
1023                            StringUtil.split(entry.getTrackbacks()));
1024    
1025                    Set<String> validTrackbacks = new HashSet<String>();
1026    
1027                    for (String trackback : trackbacksSet) {
1028                            if (oldTrackbacks.contains(trackback)) {
1029                                    continue;
1030                            }
1031    
1032                            try {
1033                                    if (LinkbackProducerUtil.sendTrackback(trackback, parts)) {
1034                                            validTrackbacks.add(trackback);
1035                                    }
1036                            }
1037                            catch (Exception e) {
1038                                    _log.error("Error while sending trackback at " + trackback, e);
1039                            }
1040                    }
1041    
1042                    if (!validTrackbacks.isEmpty()) {
1043                            String newTrackbacks = StringUtil.merge(validTrackbacks);
1044    
1045                            if (Validator.isNotNull(entry.getTrackbacks())) {
1046                                    newTrackbacks += StringPool.COMMA + entry.getTrackbacks();
1047                            }
1048    
1049                            entry.setTrackbacks(newTrackbacks);
1050    
1051                            blogsEntryPersistence.update(entry, false);
1052                    }
1053            }
1054    
1055            protected void validate(String title, String content)
1056                    throws PortalException {
1057    
1058                    if (Validator.isNull(title)) {
1059                            throw new EntryTitleException();
1060                    }
1061                    else if (Validator.isNull(content)) {
1062                            throw new EntryContentException();
1063                    }
1064            }
1065    
1066            private static Log _log = LogFactoryUtil.getLog(
1067                    BlogsEntryLocalServiceImpl.class);
1068    
1069    }