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