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