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