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