1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   * 
13   */
14  
15  package com.liferay.portlet.blogs.service.impl;
16  
17  import com.liferay.portal.PortalException;
18  import com.liferay.portal.SystemException;
19  import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
20  import com.liferay.portal.kernel.log.Log;
21  import com.liferay.portal.kernel.log.LogFactoryUtil;
22  import com.liferay.portal.kernel.search.BooleanClauseOccur;
23  import com.liferay.portal.kernel.search.BooleanQuery;
24  import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
25  import com.liferay.portal.kernel.search.Field;
26  import com.liferay.portal.kernel.search.Hits;
27  import com.liferay.portal.kernel.search.SearchEngineUtil;
28  import com.liferay.portal.kernel.search.SearchException;
29  import com.liferay.portal.kernel.util.ContentTypes;
30  import com.liferay.portal.kernel.util.GetterUtil;
31  import com.liferay.portal.kernel.util.HtmlUtil;
32  import com.liferay.portal.kernel.util.Http;
33  import com.liferay.portal.kernel.util.HttpUtil;
34  import com.liferay.portal.kernel.util.OrderByComparator;
35  import com.liferay.portal.kernel.util.SetUtil;
36  import com.liferay.portal.kernel.util.StringBundler;
37  import com.liferay.portal.kernel.util.StringPool;
38  import com.liferay.portal.kernel.util.StringUtil;
39  import com.liferay.portal.kernel.util.Validator;
40  import com.liferay.portal.model.Group;
41  import com.liferay.portal.model.ResourceConstants;
42  import com.liferay.portal.model.User;
43  import com.liferay.portal.theme.ThemeDisplay;
44  import com.liferay.portal.util.Portal;
45  import com.liferay.portal.util.PortalUtil;
46  import com.liferay.portal.util.PropsValues;
47  import com.liferay.portlet.blogs.EntryContentException;
48  import com.liferay.portlet.blogs.EntryDisplayDateException;
49  import com.liferay.portlet.blogs.EntryTitleException;
50  import com.liferay.portlet.blogs.model.BlogsEntry;
51  import com.liferay.portlet.blogs.service.base.BlogsEntryLocalServiceBaseImpl;
52  import com.liferay.portlet.blogs.social.BlogsActivityKeys;
53  import com.liferay.portlet.blogs.util.BlogsUtil;
54  import com.liferay.portlet.blogs.util.Indexer;
55  import com.liferay.portlet.blogs.util.comparator.EntryDisplayDateComparator;
56  
57  import java.io.IOException;
58  
59  import java.util.Date;
60  import java.util.HashMap;
61  import java.util.HashSet;
62  import java.util.List;
63  import java.util.Map;
64  import java.util.Set;
65  
66  import javax.xml.stream.XMLInputFactory;
67  import javax.xml.stream.XMLStreamReader;
68  
69  /**
70   * <a href="BlogsEntryLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
71   *
72   * @author Brian Wing Shun Chan
73   * @author Wilson S. Man
74   */
75  public class BlogsEntryLocalServiceImpl extends BlogsEntryLocalServiceBaseImpl {
76  
77      public BlogsEntry addEntry(
78              long userId, long plid, String title, String content,
79              int displayDateMonth, int displayDateDay, int displayDateYear,
80              int displayDateHour, int displayDateMinute, boolean draft,
81              boolean allowTrackbacks, String[] trackbacks, String[] tagsEntries,
82              boolean addCommunityPermissions, boolean addGuestPermissions,
83              ThemeDisplay themeDisplay)
84          throws PortalException, SystemException {
85  
86          return addEntry(
87              null, userId, plid, title, content, displayDateMonth,
88              displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
89              draft, allowTrackbacks, trackbacks, tagsEntries,
90              Boolean.valueOf(addCommunityPermissions),
91              Boolean.valueOf(addGuestPermissions), null, null, themeDisplay);
92      }
93  
94      public BlogsEntry addEntry(
95              String uuid, long userId, long plid, String title, String content,
96              int displayDateMonth, int displayDateDay, int displayDateYear,
97              int displayDateHour, int displayDateMinute, boolean draft,
98              boolean allowTrackbacks, String[] trackbacks, String[] tagsEntries,
99              boolean addCommunityPermissions, boolean addGuestPermissions,
100             ThemeDisplay themeDisplay)
101         throws PortalException, SystemException {
102 
103         return addEntry(
104             uuid, userId, plid, title, content, displayDateMonth,
105             displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
106             draft, allowTrackbacks, trackbacks, tagsEntries,
107             Boolean.valueOf(addCommunityPermissions),
108             Boolean.valueOf(addGuestPermissions), null, null, themeDisplay);
109     }
110 
111     public BlogsEntry addEntry(
112             long userId, long plid, String title, String content,
113             int displayDateMonth, int displayDateDay, int displayDateYear,
114             int displayDateHour, int displayDateMinute, boolean draft,
115             boolean allowTrackbacks, String[] trackbacks, String[] tagsEntries,
116             String[] communityPermissions, String[] guestPermissions,
117             ThemeDisplay themeDisplay)
118         throws PortalException, SystemException {
119 
120         return addEntry(
121             null, userId, plid, title, content, displayDateMonth,
122             displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
123             draft, allowTrackbacks, trackbacks, tagsEntries, null, null,
124             communityPermissions, guestPermissions, themeDisplay);
125     }
126 
127     public BlogsEntry addEntry(
128             String uuid, long userId, long plid, String title, String content,
129             int displayDateMonth, int displayDateDay, int displayDateYear,
130             int displayDateHour, int displayDateMinute, boolean draft,
131             boolean allowTrackbacks, String[] trackbacks, String[] tagsEntries,
132             Boolean addCommunityPermissions, Boolean addGuestPermissions,
133             String[] communityPermissions, String[] guestPermissions,
134             ThemeDisplay themeDisplay)
135         throws PortalException, SystemException {
136 
137         // Entry
138 
139         User user = userPersistence.findByPrimaryKey(userId);
140         long groupId = PortalUtil.getScopeGroupId(plid);
141 
142         Date displayDate = PortalUtil.getDate(
143             displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
144             displayDateMinute, user.getTimeZone(),
145             new EntryDisplayDateException());
146 
147         Date now = new Date();
148 
149         validate(title, content);
150 
151         long entryId = counterLocalService.increment();
152 
153         BlogsEntry entry = blogsEntryPersistence.create(entryId);
154 
155         entry.setUuid(uuid);
156         entry.setGroupId(groupId);
157         entry.setCompanyId(user.getCompanyId());
158         entry.setUserId(user.getUserId());
159         entry.setUserName(user.getFullName());
160         entry.setCreateDate(now);
161         entry.setModifiedDate(now);
162         entry.setTitle(title);
163         entry.setUrlTitle(getUniqueUrlTitle(entryId, groupId, title));
164         entry.setContent(content);
165         entry.setDisplayDate(displayDate);
166         entry.setDraft(draft);
167         entry.setAllowTrackbacks(allowTrackbacks);
168 
169         blogsEntryPersistence.update(entry, false);
170 
171         // Resources
172 
173         if ((addCommunityPermissions != null) &&
174             (addGuestPermissions != null)) {
175 
176             addEntryResources(
177                 entry, addCommunityPermissions.booleanValue(),
178                 addGuestPermissions.booleanValue());
179         }
180         else {
181             addEntryResources(entry, communityPermissions, guestPermissions);
182         }
183 
184         // Statistics
185 
186         if (!draft) {
187             blogsStatsUserLocalService.updateStatsUser(groupId, userId, now);
188         }
189 
190         // Message boards
191 
192         if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
193             mbMessageLocalService.addDiscussionMessage(
194                 userId, entry.getUserName(), BlogsEntry.class.getName(),
195                 entryId);
196         }
197 
198         // Social
199 
200         if (!draft) {
201             socialActivityLocalService.addUniqueActivity(
202                 userId, groupId, BlogsEntry.class.getName(), entryId,
203                 BlogsActivityKeys.ADD_ENTRY, StringPool.BLANK, 0);
204         }
205 
206         // Tags
207 
208         updateTagsAsset(userId, entry, tagsEntries);
209 
210         // Indexer
211 
212         reIndex(entry);
213 
214         // Ping
215 
216         pingGoogle(entry, themeDisplay);
217         pingTrackbacks(entry, trackbacks, false, themeDisplay);
218 
219         return entry;
220     }
221 
222     public void addEntryResources(
223             long entryId, boolean addCommunityPermissions,
224             boolean addGuestPermissions)
225         throws PortalException, SystemException {
226 
227         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
228 
229         addEntryResources(entry, addCommunityPermissions, addGuestPermissions);
230     }
231 
232     public void addEntryResources(
233             BlogsEntry entry, boolean addCommunityPermissions,
234             boolean addGuestPermissions)
235         throws PortalException, SystemException {
236 
237         resourceLocalService.addResources(
238             entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
239             BlogsEntry.class.getName(), entry.getEntryId(), false,
240             addCommunityPermissions, addGuestPermissions);
241     }
242 
243     public void addEntryResources(
244             long entryId, String[] communityPermissions,
245             String[] guestPermissions)
246         throws PortalException, SystemException {
247 
248         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
249 
250         addEntryResources(entry, communityPermissions, guestPermissions);
251     }
252 
253     public void addEntryResources(
254             BlogsEntry entry, String[] communityPermissions,
255             String[] guestPermissions)
256         throws PortalException, SystemException {
257 
258         resourceLocalService.addModelResources(
259             entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
260             BlogsEntry.class.getName(), entry.getEntryId(),
261             communityPermissions, guestPermissions);
262     }
263 
264     public void deleteEntries(long groupId)
265         throws PortalException, SystemException {
266 
267         for (BlogsEntry entry : blogsEntryPersistence.findByGroupId(groupId)) {
268             deleteEntry(entry);
269         }
270     }
271 
272     public void deleteEntry(long entryId)
273         throws PortalException, SystemException {
274 
275         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
276 
277         deleteEntry(entry);
278     }
279 
280     public void deleteEntry(BlogsEntry entry)
281         throws PortalException, SystemException {
282 
283         // Entry
284 
285         blogsEntryPersistence.remove(entry);
286 
287         // Resources
288 
289         resourceLocalService.deleteResource(
290             entry.getCompanyId(), BlogsEntry.class.getName(),
291             ResourceConstants.SCOPE_INDIVIDUAL, entry.getEntryId());
292 
293         // Statistics
294 
295         blogsStatsUserLocalService.updateStatsUser(
296             entry.getGroupId(), entry.getUserId());
297 
298         // Message boards
299 
300         mbMessageLocalService.deleteDiscussionMessages(
301             BlogsEntry.class.getName(), entry.getEntryId());
302 
303         // Ratings
304 
305         ratingsStatsLocalService.deleteStats(
306             BlogsEntry.class.getName(), entry.getEntryId());
307 
308         // Social
309 
310         socialActivityLocalService.deleteActivities(
311             BlogsEntry.class.getName(), entry.getEntryId());
312 
313         // Tags
314 
315         tagsAssetLocalService.deleteAsset(
316             BlogsEntry.class.getName(), entry.getEntryId());
317 
318         // Indexer
319 
320         try {
321             Indexer.deleteEntry(entry.getCompanyId(), entry.getEntryId());
322         }
323         catch (SearchException se) {
324             _log.error("Deleting index " + entry.getEntryId(), se);
325         }
326     }
327 
328     public List<BlogsEntry> getCompanyEntries(
329             long companyId, int start, int end)
330         throws SystemException {
331 
332         return blogsEntryPersistence.findByCompanyId(companyId, start, end);
333     }
334 
335     public List<BlogsEntry> getCompanyEntries(
336             long companyId, int start, int end, OrderByComparator obc)
337         throws SystemException {
338 
339         return blogsEntryPersistence.findByCompanyId(
340             companyId, start, end, obc);
341     }
342 
343     public List<BlogsEntry> getCompanyEntries(
344             long companyId, boolean draft, int start, int end)
345         throws SystemException {
346 
347         return blogsEntryPersistence.findByC_D_D(
348             companyId, new Date(), draft, start, end);
349     }
350 
351     public List<BlogsEntry> getCompanyEntries(
352             long companyId, boolean draft, int start, int end,
353             OrderByComparator obc)
354         throws SystemException {
355 
356         return blogsEntryPersistence.findByC_D_D(
357             companyId, new Date(), draft, start, end, obc);
358     }
359 
360     public int getCompanyEntriesCount(long companyId) throws SystemException {
361         return blogsEntryPersistence.countByCompanyId(companyId);
362     }
363 
364     public int getCompanyEntriesCount(long companyId, boolean draft)
365         throws SystemException {
366 
367         return blogsEntryPersistence.countByC_D_D(companyId, new Date(), draft);
368     }
369 
370     public BlogsEntry[] getEntriesPrevAndNext(long entryId)
371         throws PortalException, SystemException {
372 
373         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
374 
375         return blogsEntryPersistence.findByGroupId_PrevAndNext(
376             entry.getEntryId(), entry.getGroupId(),
377             new EntryDisplayDateComparator(true));
378     }
379 
380     public BlogsEntry getEntry(long entryId)
381         throws PortalException, SystemException {
382 
383         return blogsEntryPersistence.findByPrimaryKey(entryId);
384     }
385 
386     public BlogsEntry getEntry(long groupId, String urlTitle)
387         throws PortalException, SystemException {
388 
389         return blogsEntryPersistence.findByG_UT(groupId, urlTitle);
390     }
391 
392     public List<BlogsEntry> getGroupEntries(long groupId, int start, int end)
393         throws SystemException {
394 
395         return blogsEntryPersistence.findByGroupId(groupId, start, end);
396     }
397 
398     public List<BlogsEntry> getGroupEntries(
399             long groupId, int start, int end, OrderByComparator obc)
400         throws SystemException {
401 
402         return blogsEntryPersistence.findByGroupId(groupId, start, end, obc);
403     }
404 
405     public List<BlogsEntry> getGroupEntries(
406             long groupId, boolean draft, int start, int end)
407         throws SystemException {
408 
409         return blogsEntryPersistence.findByG_D_D(
410             groupId, new Date(), draft, start, end);
411     }
412 
413     public List<BlogsEntry> getGroupEntries(
414             long groupId, boolean draft, int start, int end,
415             OrderByComparator obc)
416         throws SystemException {
417 
418         return blogsEntryPersistence.findByG_D_D(
419             groupId, new Date(), draft, start, end, obc);
420     }
421 
422     public int getGroupEntriesCount(long groupId) throws SystemException {
423         return blogsEntryPersistence.countByGroupId(groupId);
424     }
425 
426     public int getGroupEntriesCount(long groupId, boolean draft)
427         throws SystemException {
428 
429         return blogsEntryPersistence.countByG_D_D(groupId, new Date(), draft);
430     }
431 
432     public List<BlogsEntry> getGroupUserEntries(
433             long groupId, long userId, int start, int end)
434         throws SystemException {
435 
436         return blogsEntryPersistence.findByG_U(groupId, userId, start, end);
437     }
438 
439     public List<BlogsEntry> getGroupUserEntries(
440             long groupId, long userId, int start, int end,
441             OrderByComparator obc)
442         throws SystemException {
443 
444         return blogsEntryPersistence.findByG_U(
445             groupId, userId, start, end, obc);
446     }
447 
448     public List<BlogsEntry> getGroupUserEntries(
449             long groupId, long userId, boolean draft, int start, int end)
450         throws SystemException {
451 
452         return blogsEntryPersistence.findByG_U_D_D(
453             groupId, userId, new Date(), draft, start, end);
454     }
455 
456     public List<BlogsEntry> getGroupUserEntries(
457             long groupId, long userId, boolean draft, int start, int end,
458             OrderByComparator obc)
459         throws SystemException {
460 
461         return blogsEntryPersistence.findByG_U_D_D(
462             groupId, userId, new Date(), draft, start, end, obc);
463     }
464 
465     public int getGroupUserEntriesCount(long groupId, long userId)
466         throws SystemException {
467 
468         return blogsEntryPersistence.countByG_U(groupId, userId);
469     }
470 
471     public int getGroupUserEntriesCount(
472             long groupId, long userId, boolean draft)
473         throws SystemException {
474 
475         return blogsEntryPersistence.countByG_U_D_D(
476             groupId, userId, new Date(), draft);
477     }
478 
479     public List<BlogsEntry> getNoAssetEntries() throws SystemException {
480         return blogsEntryFinder.findByNoAssets();
481     }
482 
483     public List<BlogsEntry> getOrganizationEntries(
484             long organizationId, boolean draft, int start, int end)
485         throws SystemException {
486 
487         return blogsEntryFinder.findByOrganizationId(
488             organizationId, new Date(), draft, start, end);
489     }
490 
491     public int getOrganizationEntriesCount(long organizationId, boolean draft)
492         throws SystemException {
493 
494         return blogsEntryFinder.countByOrganizationId(
495             organizationId, new Date(), draft);
496     }
497 
498     /**
499      * @deprecated {@link BlogsUtil#getUrlTitle(long, String)}
500      */
501     public String getUrlTitle(long entryId, String title) {
502         return BlogsUtil.getUrlTitle(entryId, title);
503     }
504 
505     public void reIndex(long entryId) throws SystemException {
506         if (SearchEngineUtil.isIndexReadOnly()) {
507             return;
508         }
509 
510         BlogsEntry entry = blogsEntryPersistence.fetchByPrimaryKey(entryId);
511 
512         if (entry == null) {
513             return;
514         }
515 
516         reIndex(entry);
517     }
518 
519     public void reIndex(BlogsEntry entry) throws SystemException {
520         if (entry.isDraft()) {
521             return;
522         }
523 
524         long companyId = entry.getCompanyId();
525         long groupId = entry.getGroupId();
526         long userId = entry.getUserId();
527         String userName = entry.getUserName();
528         long entryId = entry.getEntryId();
529         String title = entry.getTitle();
530         String content = entry.getContent();
531         Date displayDate = entry.getDisplayDate();
532 
533         String[] tagsEntries = tagsEntryLocalService.getEntryNames(
534             BlogsEntry.class.getName(), entryId);
535 
536         try {
537             Indexer.updateEntry(
538                 companyId, groupId, userId, userName, entryId, title, content,
539                 displayDate, tagsEntries);
540         }
541         catch (SearchException se) {
542             _log.error("Reindexing " + entryId, se);
543         }
544     }
545 
546     public void reIndex(String[] ids) throws SystemException {
547         if (SearchEngineUtil.isIndexReadOnly()) {
548             return;
549         }
550 
551         long companyId = GetterUtil.getLong(ids[0]);
552 
553         try {
554             reIndexEntries(companyId);
555         }
556         catch (SystemException se) {
557             throw se;
558         }
559         catch (Exception e) {
560             throw new SystemException(e);
561         }
562     }
563 
564     public Hits search(
565             long companyId, long groupId, long userId, String keywords,
566             int start, int end)
567         throws SystemException {
568 
569         try {
570             BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
571 
572             contextQuery.addRequiredTerm(Field.PORTLET_ID, Indexer.PORTLET_ID);
573 
574             if (groupId > 0) {
575                 contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
576             }
577 
578             if (userId > 0) {
579                 contextQuery.addRequiredTerm(Field.USER_ID, userId);
580             }
581 
582             BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
583 
584             if (Validator.isNotNull(keywords)) {
585                 searchQuery.addTerm(Field.USER_NAME, keywords);
586                 searchQuery.addTerm(Field.TITLE, keywords);
587                 searchQuery.addTerm(Field.CONTENT, keywords);
588                 searchQuery.addTerm(Field.TAGS_ENTRIES, keywords, true);
589             }
590 
591             BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
592 
593             fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
594 
595             if (searchQuery.clauses().size() > 0) {
596                 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
597             }
598 
599             return SearchEngineUtil.search(companyId, fullQuery, start, end);
600         }
601         catch (Exception e) {
602             throw new SystemException(e);
603         }
604     }
605 
606     public BlogsEntry updateEntry(
607             long userId, long entryId, String title, String content,
608             int displayDateMonth, int displayDateDay, int displayDateYear,
609             int displayDateHour, int displayDateMinute, boolean draft,
610             boolean allowTrackbacks, String[] trackbacks, String[] tagsEntries,
611             ThemeDisplay themeDisplay)
612         throws PortalException, SystemException {
613 
614         // Entry
615 
616         User user = userPersistence.findByPrimaryKey(userId);
617 
618         Date displayDate = PortalUtil.getDate(
619             displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
620             displayDateMinute, user.getTimeZone(),
621             new EntryDisplayDateException());
622 
623         validate(title, content);
624 
625         BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
626 
627         String oldUrlTitle = entry.getUrlTitle();
628 
629         entry.setModifiedDate(new Date());
630         entry.setTitle(title);
631         entry.setUrlTitle(
632             getUniqueUrlTitle(entryId, entry.getGroupId(), title));
633         entry.setContent(content);
634         entry.setDisplayDate(displayDate);
635         entry.setDraft(draft);
636         entry.setAllowTrackbacks(allowTrackbacks);
637 
638         blogsEntryPersistence.update(entry, false);
639 
640         // Statistics
641 
642         if (!draft) {
643             blogsStatsUserLocalService.updateStatsUser(
644                 entry.getGroupId(), entry.getUserId(), displayDate);
645         }
646 
647         // Social
648 
649         if (!draft) {
650             socialActivityLocalService.addUniqueActivity(
651                 userId, entry.getGroupId(), BlogsEntry.class.getName(), entryId,
652                 BlogsActivityKeys.ADD_ENTRY, StringPool.BLANK, 0);
653         }
654 
655         // Tags
656 
657         updateTagsAsset(userId, entry, tagsEntries);
658 
659         // Indexer
660 
661         if (!draft) {
662             reIndex(entry);
663         }
664         else {
665             try {
666                 Indexer.deleteEntry(entry.getCompanyId(), entryId);
667             }
668             catch (SearchException se) {
669                 _log.error("Deleting index " + entry.getEntryId(), se);
670             }
671         }
672 
673         // Ping
674 
675         pingGoogle(entry, themeDisplay);
676 
677         boolean pingOldTrackbacks = false;
678 
679         if (!oldUrlTitle.equals(entry.getUrlTitle())) {
680             pingOldTrackbacks = true;
681         }
682 
683         pingTrackbacks(entry, trackbacks, pingOldTrackbacks, themeDisplay);
684 
685         return entry;
686     }
687 
688     public void updateTagsAsset(
689             long userId, BlogsEntry entry, String[] tagsEntries)
690         throws PortalException, SystemException {
691 
692         tagsAssetLocalService.updateAsset(
693             userId, entry.getGroupId(), BlogsEntry.class.getName(),
694             entry.getEntryId(), tagsEntries, null, null, entry.getDisplayDate(),
695             null, ContentTypes.TEXT_HTML, entry.getTitle(), null, null, null, 0,
696             0, null, false);
697     }
698 
699     protected String getUniqueUrlTitle(
700             long entryId, long groupId, String title)
701         throws SystemException {
702 
703         String urlTitle = BlogsUtil.getUrlTitle(entryId, title);
704 
705         String newUrlTitle = urlTitle;
706 
707         for (int i = 1;; i++) {
708             BlogsEntry entry = blogsEntryPersistence.fetchByG_UT(
709                 groupId, newUrlTitle);
710 
711             if ((entry == null) || (entry.getEntryId() == entryId)) {
712                 break;
713             }
714             else {
715                 newUrlTitle = urlTitle + StringPool.DASH + i;
716             }
717         }
718 
719         return newUrlTitle;
720     }
721 
722     protected void pingGoogle(BlogsEntry entry, ThemeDisplay themeDisplay)
723         throws PortalException, SystemException {
724 
725         if (!PropsValues.BLOGS_PING_GOOGLE_ENABLED || !entry.isApproved()) {
726             return;
727         }
728 
729         if (themeDisplay == null) {
730             return;
731         }
732 
733         String layoutFullURL = PortalUtil.getLayoutFullURL(themeDisplay);
734 
735         if (Validator.isNull(layoutFullURL)) {
736             return;
737         }
738 
739         if (layoutFullURL.contains("://localhost")) {
740             if (_log.isDebugEnabled()) {
741                 _log.debug(
742                     "Not pinging Google because of localhost URL " +
743                         layoutFullURL);
744             }
745 
746             return;
747         }
748 
749         Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
750 
751         StringBundler sb = new StringBundler(6);
752 
753         String name = group.getDescriptiveName();
754         String url = layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs";
755         String changesURL =
756             layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/rss";
757 
758         sb.append("http://blogsearch.google.com/ping?name=");
759         sb.append(HttpUtil.encodeURL(name));
760         sb.append("&url=");
761         sb.append(HttpUtil.encodeURL(url));
762         sb.append("&changesURL=");
763         sb.append(HttpUtil.encodeURL(changesURL));
764 
765         String location = sb.toString();
766 
767         if (_log.isInfoEnabled()) {
768             _log.info("Pinging Google at " + location);
769         }
770 
771         try {
772             String response = HttpUtil.URLtoString(sb.toString());
773 
774             if (_log.isInfoEnabled()) {
775                 _log.info("Google ping response: " + response);
776             }
777         }
778         catch (IOException ioe) {
779             _log.error("Unable to ping Google at " + location, ioe);
780         }
781     }
782 
783     protected boolean pingTrackback(String trackback, Map<String, String> parts)
784         throws Exception {
785 
786         if (_log.isDebugEnabled()) {
787             _log.debug("Pinging trackback " + trackback);
788         }
789 
790         Http.Options options = new Http.Options();
791 
792         options.setLocation(trackback);
793         options.setParts(parts);
794         options.setPost(true);
795 
796         String xml = HttpUtil.URLtoString(options);
797 
798         if (_log.isDebugEnabled()) {
799             _log.debug(xml);
800         }
801 
802         XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
803 
804         XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(
805             new UnsyncStringReader(xml));
806 
807         String error = xml;
808 
809         try {
810             xmlStreamReader.nextTag();
811             xmlStreamReader.nextTag();
812 
813             String name = xmlStreamReader.getLocalName();
814 
815             if (name.equals("error")) {
816                 int status = GetterUtil.getInteger(
817                     xmlStreamReader.getElementText(), 1);
818 
819                 if (status == 0) {
820                     return true;
821                 }
822 
823                 xmlStreamReader.nextTag();
824 
825                 name = xmlStreamReader.getLocalName();
826 
827                 if (name.equals("message")) {
828                     error = xmlStreamReader.getElementText();
829                 }
830             }
831         }
832         finally {
833             if (xmlStreamReader != null) {
834                 try {
835                     xmlStreamReader.close();
836                 }
837                 catch (Exception e) {
838                 }
839             }
840         }
841 
842         _log.error(
843             "Error while pinging trackback at " + trackback + ": " + error);
844 
845         return false;
846     }
847 
848     protected void pingTrackbacks(
849             BlogsEntry entry, String[] trackbacks, boolean pingOldTrackbacks,
850             ThemeDisplay themeDisplay)
851         throws SystemException {
852 
853         if (!PropsValues.BLOGS_TRACKBACK_ENABLED ||
854             !entry.isAllowTrackbacks() || !entry.isApproved()) {
855 
856             return;
857         }
858 
859         if (themeDisplay == null) {
860             return;
861         }
862 
863         String layoutFullURL = PortalUtil.getLayoutFullURL(themeDisplay);
864 
865         Map<String, String> parts = new HashMap<String, String>();
866 
867         String excerpt = StringUtil.shorten(
868             HtmlUtil.extractText(entry.getContent()),
869             PropsValues.BLOGS_TRACKBACK_EXCERPT_LENGTH);
870         String url =
871             layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
872                 entry.getUrlTitle();
873 
874         parts.put("title", entry.getTitle());
875         parts.put("excerpt", excerpt);
876         parts.put("url", url);
877         parts.put("blog_name", entry.getUserName());
878 
879         Set<String> trackbacksSet = null;
880 
881         if (Validator.isNotNull(trackbacks)) {
882             trackbacksSet = SetUtil.fromArray(trackbacks);
883         }
884         else {
885             trackbacksSet = new HashSet<String>();
886         }
887 
888         if (pingOldTrackbacks) {
889             trackbacksSet.addAll(
890                 SetUtil.fromArray(StringUtil.split(entry.getTrackbacks())));
891 
892             entry.setTrackbacks(StringPool.BLANK);
893 
894             blogsEntryPersistence.update(entry, false);
895         }
896 
897         Set<String> oldTrackbacks = SetUtil.fromArray(
898             StringUtil.split(entry.getTrackbacks()));
899 
900         Set<String> validTrackbacks = new HashSet<String>();
901 
902         for (String trackback : trackbacksSet) {
903             if (oldTrackbacks.contains(trackback)) {
904                 continue;
905             }
906 
907             try {
908                 if (pingTrackback(trackback, parts)) {
909                     validTrackbacks.add(trackback);
910                 }
911             }
912             catch (Exception e) {
913                 _log.error("Error while pinging trackback at " + trackback, e);
914             }
915         }
916 
917         if (!validTrackbacks.isEmpty()) {
918             String newTrackbacks = StringUtil.merge(validTrackbacks);
919 
920             if (Validator.isNotNull(entry.getTrackbacks())) {
921                 newTrackbacks += StringPool.COMMA + entry.getTrackbacks();
922             }
923 
924             entry.setTrackbacks(newTrackbacks);
925 
926             blogsEntryPersistence.update(entry, false);
927         }
928     }
929 
930     protected void reIndexEntries(long companyId) throws SystemException {
931         int count = blogsEntryPersistence.countByCompanyId(companyId);
932 
933         int pages = count / Indexer.DEFAULT_INTERVAL;
934 
935         for (int i = 0; i <= pages; i++) {
936             int start = (i * Indexer.DEFAULT_INTERVAL);
937             int end = start + Indexer.DEFAULT_INTERVAL;
938 
939             reIndexEntries(companyId, start, end);
940         }
941     }
942 
943     protected void reIndexEntries(long companyId, int start, int end)
944         throws SystemException {
945 
946         List<BlogsEntry> entries = blogsEntryPersistence.findByCompanyId(
947             companyId, start, end);
948 
949         for (BlogsEntry entry : entries) {
950             reIndex(entry);
951         }
952     }
953 
954     protected void validate(String title, String content)
955         throws PortalException {
956 
957         if (Validator.isNull(title)) {
958             throw new EntryTitleException();
959         }
960         else if (Validator.isNull(content)) {
961             throw new EntryContentException();
962         }
963     }
964 
965     private static Log _log = LogFactoryUtil.getLog(
966         BlogsEntryLocalServiceImpl.class);
967 
968 }